想自己建一个游戏框架……但是看了好多框架也没有一个从头教的,唉,先自己摸索吧
去看了别人介绍 PureMVC 的文章,不知道什么模式啥的,根本看不懂……先看设计模式吧
设计模式教程
https://www.runoob.com/design-pattern/factory-pattern.html
1.工厂模式
教程里面的代码是:
要用 funA 返回一个 classA
根据 funA 参数分情况讨论,返回经过不同处理的 classA
一般来说就直接通过 switch 就好了,但这个“不同处理”可以也可以用子类实现。
也就是说,根据 funA 参数分情况创建 classA 的不同子类 classA1,classA2……,并对这些子类调用相同的方法,而不同子类中对这个方法有不同的实现,最后 funA 把子类 classA1,classA2…… 转换到基类 classA,返回 classA
其实就是把 switch 的任务,使用相同的方法名,分到各个子类方法里面
伪代码:
直接使用一个函数解决问题:
funA(arg)
{
switch(arg)
{
case 1: return fun1();
case 2: return fun2();
//...
}
}
使用工厂模式解决问题:
funA(arg)
{
ClassA ins;
switch(arg)
{
case 1: ins = new classA1(); break;
case 2: ins = new classA2(); break;
//...
}
return ins.interfaceA();
}
// 也可以把这个 classA 叫做接口
classA
{
interfaceA();
}
classA1 implement classA
{
override interfaceA();
}
classA2 implement classA
{
override interfaceA();
}
//...
classA1::interfaceA()
{
return fun1();
}
classA2::interfaceA()
{
return fun2();
}
//...
2.抽象工厂模式
感觉就是工厂模式的组合而已
伪代码:
直接使用一个函数解决问题:
funA(arg)
{
Ans ans1;
Ans ans2;
switch(arg[0])
{
case 1: ans1 = fun1_1();
case 2: ans1 = fun1_2();
//...
}
switch(arg[1])
{
case 1: ans2 = fun2_1();
case 2: ans2 = fun2_2();
//...
}
return [ans1, ans2];
}
使用组合工厂模式解决问题:
funA(arg)
{
ClassA ins1;
ClassB ins2;
switch(arg[0])
{
case 1: ins1 = new classA1(); break;
case 2: ins1 = new classA2(); break;
//...
}
switch(arg[1])
{
case 1: ins2 = new classB1(); break;
case 2: ins2 = new classB2(); break;
//...
}
return [ins1.interfaceA(), ins2.interfaceB()];
}
// 也可以把这个 classA 叫做接口
classA
{
interfaceA();
}
classA1 implement classA
{
override interfaceA();
}
classA2 implement classA
{
override interfaceA();
}
//...
classA1::interfaceA()
{
return fun1_1();
}
classA2::interfaceA()
{
return fun1_2();
}
//...
// 也可以把这个 classB 叫做接口
classB
{
interfaceB();
}
classB1 implement classB
{
override interfaceB();
}
classB2 implement classB
{
override interfaceB();
}
//...
classB1::interfaceB()
{
return fun2_1();
}
classA2::interfaceA()
{
return fun2_2();
}
//...
3.单例模式
类是可以实例化的
普通的类的成员可以实例化出来多份
想要这个类的某一个成员只有一份,就是希望单例
类的静态成员就是单例
还要考虑多个线程同时访问这个单例的情况
教程中的代码挺清晰
4.建造者模式
感觉跟组合工厂没啥区别……
5.原型模式
程序中需要多次用到 classA1 classA2 的实例,但是实例化这些类的代价高昂
如果 classA1 classA2 的实例只有有限个状态,那么可以提前对每一个类实例化不同状态下的实例,需要用的时候返回浅拷贝
伪代码:
运行时实例化:
funA()
{
// start
// do some things...
ins1 = new classA();
ins1 = process1(ins1);
use1(ins1);
ins2 = new classA();
ins2 = process2(ins2);
use2(ins2);
}
提前实例化,使用时返回浅拷贝:
funA()
{
// start
ins1 = new classA();
ins1 = process1(ins1);
ins2 = new classA();
ins2 = process2(ins2);
Map insMap;
insMap.put(key1,ins1);
insMap.put(key2,ins2);
// do some things...
use1(insMap[key1].shallowcopy());
use2(insMap[key2].shallowcopy());
}
6.适配器模式
要在原来的 switch 上添加情况,可以用一个子类处理新的情况
伪代码:
直接使用一个函数解决问题:
旧版本:
funA(arg)
{
switch(arg)
{
case 1: return fun1();
}
}
新版本:
funA(arg)
{
switch(arg)
{
case 1: return fun1();
case 2: return fun2();
//...
}
}
使用适配器模式解决问题:
旧版本:
funA(arg)
{
ClassA ins;
switch(arg)
{
case 1: ins = new classA1(); break;
}
return ins.interfaceA();
}
// 也可以把这个 classA 叫做接口
classA
{
interfaceA();
}
classA1 implement classA
{
override interfaceA();
}
//...
classA1::interfaceA()
{
return fun1();
}
//...
新版本:
funA(arg)
{
ClassA ins;
switch(arg)
{
case 1: ins = new classA1(); break;
case 2: ins = new classA2(); break;
//...
}
return ins.interfaceA();
}
// 也可以把这个 classA 叫做接口
classA
{
interfaceA();
}
classA1 implement classA
{
override interfaceA();
}
classA2 implement classA
{
override interfaceA();
}
//...
classA1::interfaceA()
{
return fun1();
}
// classA2 就是适配器
classA2::interfaceA()
{
return fun2();
}
//...
7.桥接模式
一个类有若干个角度,每一个角度都有 n 个实现需求
那么通过继承就要创建 ∏ni 个子类,会很多
伪代码:
classAB(arg)
{
classA insA;
switch(arg[0])
{
case 1: insA = new classA1(); break;
case 2: insA = new classA2(); break;
//...
}
classB insB;
switch(arg[1])
{
case 1: insB = new classB1(); break;
case 2: insB = new classB2(); break;
//...
}
}
感觉跟组合没什么区别欸
8.过滤器模式
类提供一个可供筛选的 tag
现在有一个过滤器类,输入类的实例的列表,根据 tag 筛选出符合条件的类的实例的列表
9.组合模式
组件的组合……看过 ecs 了就不多解释了
10.装饰器模式
类 B 里面存类 A,基于类 A 的方法新建方法,但不继承类 A
好像跟桥接、组合也没区别……
这么看来还是组合最纯粹
11.外观模式
感觉跟工厂模式也是一样的,只是工厂模式是根据输入参数的不同调用不同的类,这个是根据使用函数的不同调用不同的类
12.享元模式
类的实例可能被多次用到,因此第一次用到时,创建好存在 Map 里面,要用到了就拿出来
13.代理模式
同样是类似适配器、装饰器的组合思路,基于类 A 实现方法,这个方法是用于控制的
14.责任链模式
一个链表,链表成员是不同的类的实例,他们有一个身份标识,实现相同的接口,知道 next。从头结点开始匹配身份标识,是则调用接口,不是则跳到 next
15.命令模式
把一个执行流程拆成请求者,请求,发送者
伪代码:
class Sender;
class Request;
class Receiver;
class Sender
{
makeRequest();
}
Sender::makeRequest()
{
return new Request();
}
class Request
{
process();
}
class Receiver()
{
List requestList;
addRequestToList(Request);
ProcessRequestList();
}
Receiver::addRequestToList(Request q)
{
requestList.add(q);
}
Receiver::ProcessRequestList()
{
for(q : requestList)
q.process();
requestList.clear();
}
16.解释器模式
跟过滤器很像,都是对一个东西条件匹配
17.迭代器模式
学过 C++ 的都知道
class Iterator
{
next();
}
class Container
{
Iterator iter;
}
main()
{
List containerList;
for(Iterator iter = containerList[0];iter;)
{
// do some thing
iter = iter.next();
}
}
18.中介者模式
网状结构转化成星形结构,中介者就是星形的那个中间节点
19.备忘录模式
保存回滚对象的状态
更进一步,可以细分为
获取对象状态
对象状态仓库
恢复对象状态
20.观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
原来我们改变一个类的实例的属性的时候就直接访问然后修改了
按照这个思路,假设我不知道谁动了这个属性,但我还是要知道什么时候这个属性变了的话,那我就只能在一个死循环里面不断查看这个属性,和旧值比较,不相等就是改变了
这样做是很简单但是很蠢的方法
为了性能,必须要做复杂一点,加些约束
那么这个约束就是,我规定修改这个类的实例的属性只能通过一个函数来修改
这样的话,其他人都用这个函数,我就知道,这个函数被调用的时候就是属性被修改的时候,其他任何时候属性都不会变
伪代码:
class Client
{
Data data;
}
class ProcessWithNotify
{
List observersList;
Process(Client,function);
}
ProcessWithNotify::Process(Client c,function processFun)
{
processFun(&(c.data))
for(ob : observersList)
ob.Update();
}
class Observer
{
Update();
}
21.状态模式
状态机
22.空对象模式
在数据不可用的时候提供默认的行为
好像跟工厂模式也差不多……
伪代码:
funA(arg)
{
ClassA ins;
switch(isValid(arg))
{
case true: ins = new realClassA(); break;
case false: ins = new emptyClassA(); break;
//...
}
return ins.interfaceA();
}
// 也可以把这个 classA 叫做接口
classA
{
interfaceA();
}
realClassAimplement classA
{
override interfaceA();
}
emptyClassA implement classA
{
override interfaceA();
}
//...
realClassA::interfaceA()
{
return fun1();
}
emptyClassA::interfaceA()
{
return fun2();
}
//...
23.策略模式
同样是运行时改变行为
状态机希望状态时长时间保持不变的
策略模式是对于每一次调用都可能改变行为
其他应该没有区别
24.模板模式
期望在子类中实现方法的细节
感觉就是普通的继承
25.访问者模式
一个类 A 对于 类 B1,B2,B3 的访问,有函数定义 fun1,fun2,fun3
26.MVC模式
模型保存数据
视图用于可视化
控制器处理数据
27.业务代表模式
感觉跟策略模式是一样的,只是用在服务器的语境下
28.组合实体模式
不断地组合下去……我也没看懂多层组合是用来干啥的
29.数据访问对象模式
数据库
30.前端控制器模式
控制器处理请求
控制器中有调度器,请求通过就使用自己的调度器成员
调度器控制视图
31.拦截过滤器模式
跟过滤器模式一样,得到具有符合条件的 tag 的实体
32.服务定位器模式
跟原型模式一样,把要用的东西缓存起来
33.传输对象模式
简单的传输数据