总体来说设计模式分为三大类:
1. 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
2. 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
3. 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
引入设计模式目的是:降低程序间的耦合性,方便扩展;增加代码复用率。
现学习最常用的10种设计模式。
#### 工厂模式
1、2工厂操作继承自同一基类的原因:两工厂的操作接口相同
产品继承自同一基类的原因:操作接口相同、用到多态。
AbstractProduct* productA1=Factory1.createProductA();//指向ProductA_1
AbstractProduct* productA2=Factory2.createProductA();//指向ProductA_2
然后执行
productA1->operationA();
productA2-> operationA();//应用多态实现不同操作
应用特点:增减产品容易,只需要在factory内增加一项产品C,然后写一个C类即可。
模板模式
在抽象模板class内给出购物流程。即依次selectProduct,addToCart,account,shopping,但未详细说明这些步骤怎样执行,需要程序员通过继承的方式定义这些函数。
例子如下完成了京东购物:
OnlineShopping* jingdong=new Jingdong();
jingdong->selectProduct();
jingdong->addToCart();
jingdong->account();
jingdong->shopping();
策略模式
对不同算法进行封装。
比如给出了苹果、西瓜、香蕉的吃法,且A、B、C三位同学吃苹果、西瓜、香蕉的方式相同,但吃这三种水果的顺序不同。
可对这个问题进行抽象,吃水果的方式可看作已经定义的API,吃水果的顺序可看作不同算法。
class eating{
public:
void apple(){cout<<”eat apple”<<endle;return};
void watermelon(){cout<<”eat watermelon”<<endle;return};
void banana(){cout<<”eat banana”<<endle;return};
};
不同算法把这些函数指针当作参数,进行不同的排列组合
Strategy* A=new StrategyA();
A->Algorithom(apple,watermelon,banana);//这就给出了A吃水果的顺序。
同样使用到了多态,模板模式和策略模式有什么不同呢?
简单来说模板模式给出了生产线的执行流程,但每个环节该怎么做,由程序员给出;策略模式给出了生产线所有环节的操作方法,但应该按照怎样的次序(算法)来组织这些环节,由程序员给出。
工厂模式方便扩展产品;策略模式方便扩展算法。
装饰器模式
目的:在不改变原有程序的基础上对原有的类进行封装,扩展或修改其部分功能。
如图封装原类的指针,并重载部分原有的函数(修改部分功能),再添加一些新的函数。
为什么要继承base?
使得base类型指针仍然能够指向新的decorator。
适配器模式
封装原有的类,按需提供API。
见STL的容器适配器、迭代器适配器、仿函数适配器。
装饰器、适配器、普通继承都属于对原类的封装,它们有什么不同呢?
1. 适配器模式的意义是要将一个接口转变成另外一个接口,它的目的是通过改变接口来达到重复使用的目的;
2. 装饰器模式不要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强原有接口的功能,或者改变原有对象的处理方法而提升性能;
代理模式
如图proxy封装有base* 类型指针ptr,由构造函数proxy(name)决定ptr指向谁,如果指向“张三”,则由张三的成员函数初始化proxy的成员函数。
base* proxy1(“zhangsan”);
proxy1->age();//显示张三的年龄
base* proxy2(“lisi”);
proxy2->age();//显示李四的年龄
责任链模式
目的:减少if else语句
比如给出一个int val=33;A封装有0~20,B 20~40,C 40~60。
现给出程序:
A a;
B b;
C c;
a.setnext(b);
b.setnext(c);
a.process(val);
process的实现,以A的process实现为例:
A::process(val)
{
if(val>0&&val<=20) cout<<”小”<<endl;
else nextptr->process(val);
return;
}
观察者模式
add:添加观察者,即向vector中添加base*指针;
delete:删除某个观察者;
notify_all:通知所有挂接在vector上的类,也就是执行notify_all时,会依次调用所有observer的成员函数。
单例模式
用于保证该类型实例只有一个。
实现方法:
构造函数设置为私有,通过公有部分的getInstance()调用构造函数实现类的实例化;不能通过new实例化,因为new实例化过程会调用构造函数,而此时构造函数是私有成员,无法由new访问到。
迭代器模式
见STL中的iterator实现方法:就是给不同的数据结构提供统一的访问接口。