设计模式
- 序
- 创建型模式
- 工厂方法模式
- 抽象工厂模式
- 单例模式
- 建造者模式(生成器模式)
- 原型模式
- 结构型模式
- 适配器模式
- 装饰器
- 代理模式
- 外观模式
- 桥接模式
- 组合模式(部分--整体模式)
- 享元模式
- 行为型模式
- 策略模式
- 模板模式
- 观察者模式
- 迭代器模式
- 责任链模式
- 命令模式
- 状态模式
- 备忘录模式(快照模式)
- 访问者模式
- 中介者模式
- 解释器模式
序
设计模式,依据设计目的分为三种:创建型模式、结构型模式、行为型模式
创建型模式包括:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式包括:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式包括:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
创建型模式
工厂方法模式
由自己根据需要直接实例化对象
OBJ *obj;
if []
obj = new obj1();
else
obj = new obj2();
抽象工厂模式
由工厂分发对象
OBJ obj = Factory("xxx");
单例模式
全局仅一个该类型对象,可以在尝试使用时候实例化,也可以程序初始化(编译、程序启动时候)时候实例化
OBJ::GetInstance();
建造者模式(生成器模式)
某些对象的初始化需要多个步骤完成,可以将它交给一个director来初始化,以此达到统一的代码实现
O o;
o.setBuilder(builder)
o.builder();
原型模式
单纯一个深拷贝
OBJ obj1
OBJ obj2(obj1)
结构型模式
适配器模式
没什么好说的,就是将同种功能,但实现方式不同的接口、类按照一致的形态进行编写,达到可以任意切换接口、类的目的
装饰器
实现方式有些类似于回调函数,以完成对所需要增加的属性值一一调用接口增加的目的
class Parent
{
virtual void Fun(void)=0;
}
class Product : public Parent{
void Fun(void) override
{
//TODO: pass
}
}
class decorator1: public Parent{
decorator1(Parent & parent):_parent(parent){};
void Fun(void) override
{
_parent.Fun();
}
Parent &_parent;
}
class decorator2: public Parent{
decorator2(Parent & parent):_parent(parent){};
void Fun(void) override
{
_parent.Fun();
}
Parent &_parent;
}
相关代码
代理模式
使用代理服务,隐藏原本的类,可用于团队开发,各自负责各自的部分,也可以使用一个小一点的class暴漏或者分等级暴露接口,减少系统维护难度
下述代码可以使用委托类的Request接口
template<class T>
class Proxy
{
public:
Proxy(){};
Proxy(T* sub){m_sub=sub;}; //代理主题角色中定义了一个真实主题角色对象
~Proxy(){delete m_sub;};
void Request() //代理主题角色也实现了抽象主题角色的方法
{
cout<<"Proxy REQ"<<endl;
m_sub->Request();//代理主题角色调用 真实角色的业务方法
}
private:
T* m_sub;
};
外观模式
个人觉得比较扯淡的一个模式,好比我们喝水,非要说说喝的是H2O, 明明就是一个接口封装,逐级封装, 貌似刚学代码时候就需要了解的东西,下面是从其他博主那边找的例子
点击调准实例地址
#include <iostream>
using namespace std;
//外观模式就是将复杂的子类系统抽象到同一个接口进行管理,
//外界只需要通过此接口与子类系统进行交互,
//而不必要和复杂的子类系统进行交互
class Television //电视机类
{
public:
void On(){
cout << "电视机打开" << endl;
}
void Off() {
cout << "电视机关闭" << endl;
}
};
class Gamemachine //游戏机类
{
public:
void On() {
cout << "游戏机打开" << endl;
}
void Off() {
cout << "游戏机关闭" << endl;
}
};
class Microphone //麦克风类
{
public:
void On() {
cout << "麦克风打开" << endl;
}
void Off() {
cout << "麦克风关闭" << endl;
}
};
class Sound //音响类
{
public:
void On() {
cout << "音响打开" << endl;
}
void Off() {
cout << "音响关闭" << endl;
}
};
class Light //灯类
{
public:
void On() {
cout << "灯打开" << endl;
}
void Off() {
cout << "灯关闭" << endl;
}
};
class DVD //DVD类
{
public:
void On() {
cout << "DVD打开" << endl;
}
void Off() {
cout << "DVD关闭" << endl;
}
};
class Facade
{
public:
Facade() {
ds = new Television;
yxj = new Gamemachine;
mkf = new Microphone;
yx = new Sound;
d = new Light;
dvd = new DVD;
}
void KTVPattern()//KTV模式
{
cout << "KTV模式启动中,请稍后!" << endl;
ds->On();
d->Off();
mkf->On();
yx->On();
dvd->On();
}
void GamePattern() //游戏机模式
{
cout << "游戏机模式启动中,请稍后!" << endl;
ds->On();
yx->On();
yxj->On();
}
~Facade() {
delete ds;
delete yxj;
delete mkf;
delete yx;
delete d;
delete dvd;
}
private:
Television*ds;
Gamemachine*yxj;
Microphone*mkf;
Sound*yx;
Light*d;
DVD*dvd;
};
void test() {
Facade*myFacade = new Facade;
myFacade->KTVPattern();
myFacade->GamePattern();
}
void main() {
test();
}
桥接模式
顾名思义,牵线搭桥。 该模式适用于双发没有从属关系、没有上下级关系的场景。
建立一个桥接类,将两个互不统属的类进行关联调用。
实际场景可以参考各个手机的应用商店功能。
相关代码
组合模式(部分–整体模式)
适用于上下级且能够抽象出一致性的场景中,
比如传销组织的结构,开个玩笑,不过传销组织的确很时候使用组合模式。
class PyramidSale {
string m_string;
virtual void add(PyramidSale *)=0;
}
class Level1 :public PyramidSale
{
vector<PyramidSale *> m_vecComp;
void add(PyramidSale *) override;
}
class Level12:public PyramidSale
{
vector<PyramidSale *> m_vecComp;
void add(PyramidSale *) override;
}
int main(void)
{
PyramidSale *l1 = new Level1();
PyramidSale *l2_1 = new Level2();
PyramidSale *l2_2 = new Level2();
l1->add(l2_1);
l1->add(l2_2);
}
享元模式
共享资源的一种模式,
由于系统开发环节中,很多资源属于能够被公用的,比如某个图片资源、某个音频资源
如果每个对象使用它的时候加载一次,耗费时间,而且多个对象同时加载同一个资源,又浪费内存资源
争对此,提出享元模式
即:某一大型资源加载时候,先查询享元类(可以理解为一个共享空间),在这个空间内使用hash map对资源进行缓存, 如果不存在, 再从flash中加载资源,否则直接从享元类中获取,节省时间与空间
享元类中可以做一个循环队列,某些长时间不使用的大型资源,可以释放掉。
代码链接
行为型模式
策略模式
与工厂模式一样,所不同的是目的不同,也就是应用场景不同,
工厂模式侧重于实例化对象,
策略模式侧重于类中接口的实现,也就是算法的实现
模板模式
class Leader {
public:
void run(void)
{
a();
b();
c();
}
virtual void a()==0;
virtual void b()==0;
virtual void c()==0;
}
class OfficClerk : Leader{
public:
void a() override
{
}
void b() override
{
}
void c() override
{
}
}
int main()
{
Leader *leader = new OfficClerk ();
leader->run();
}
观察者模式
其他作者是这么描述的:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
核心解决方案:回调函数
class Observer {
public:
virtual void update()= 0;
}
templete <class T>
class Subject {
private:
std::list<T *> _objectServerList;
public:
void attach(T *object) {
_objectServerList.push_back(t);
}
void detach(T *object) {
_objectServerList.remove(t);
}
void Notify() {
for(auto object=_objectServerList.begin();object!=_objectServerList.end();object++)
{
(*object)->update();
}
}
}
迭代器模式
一种遍历的手段,比如链表就是一种迭代器的表现方式,
责任链模式
还是定义不同的接口、或者对象,来将任务拆分成不同的任务(责任)进行
每个接口、对象完成一部分,达到简化代码的目的
命令模式
核心思想:命令模式的作用是将请求封装为一个对象,将请求的发起者和执行者解耦,支持对请求排队以及撤销和重做。
下例中,将Receiver中的两个请求封装成为了两个对象,然后通过命令来进行执行
声明:代码抄袭自链接, 然后使用模板类实现,增强适应性
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
// 接受者,作为最底层的调用
class Receiver
{
public:
void BakeMutton()
{
cout<< "烤羊肉"<< endl;
}
void BakeChicken()
{
cout<< "烤鸡翅"<< endl;
}
};
// 基类
template <class T>
class Command
{
public:
Command(T* pstReceiver):m_pstReceiver(pstReceiver)
{
cout << "m_pstReceiver" << endl;
};
~Command();
virtual void Excute() = 0;
// protected:
T* m_pstReceiver;
};
// 具体类,用于调用接收者
template <class T>
class ConcreteCommandA: public Command<T>
{
public:
ConcreteCommandA(T* pstReceiver) : Command<T>(pstReceiver)
{
}
virtual void Excute()
{
cout<< "ConcreteCommandA excuting......"<< endl;
this->m_pstReceiver->BakeMutton();
}
};
// 具体类,用于调用接收者
template <class T>
class ConcreteCommandB: public Command<T>
{
public:
ConcreteCommandB(T* pstReceiver):Command<T>(pstReceiver)
{
}
virtual void Excute()
{
cout<< "ConcreteCommandB excuting......"<< endl;
this->m_pstReceiver->BakeChicken();
}
};
// 调用者,作为最上层,用于管理具体类的操作,从而对接收者增删
template <class T>
class Invoke
{
public:
void Add(Command<T>* pstCommand)
{
m_vecPstCommand.push_back(pstCommand);
}
void Remove(Command<T>* pstCommand)
{
m_vecPstCommand.erase(find(m_vecPstCommand.begin(), m_vecPstCommand.end(), pstCommand));
}
void RemoveAll()
{
m_vecPstCommand.clear();
}
void Notify()
{
for (typeof(m_vecPstCommand.begin()) it = m_vecPstCommand.begin(); it != m_vecPstCommand.end(); ++it)
{
(*it)->Excute();
}
}
private:
vector<Command<Receiver>*> m_vecPstCommand;
};
int main(int argc, char* argv[])
{
Receiver* pstReceiver = new Receiver();
Command<Receiver>* pstConcreteCommandA = new ConcreteCommandA<Receiver>(pstReceiver);
Command<Receiver>* pstConcreteCommandB = new ConcreteCommandB<Receiver>(pstReceiver);
Invoke<Receiver>* pstInvoke = new Invoke<Receiver>();
pstInvoke->Add(pstConcreteCommandA);
pstInvoke->Add(pstConcreteCommandA);
pstInvoke->Add(pstConcreteCommandB);
pstInvoke->Notify();
cout<< "------------------"<< endl<< endl;
pstInvoke->Remove(pstConcreteCommandA); //撤销操作
pstInvoke->Remove(pstConcreteCommandB);
pstInvoke->Notify();
cout<< "------------------"<< endl<< endl;
return 0;
}
状态模式
主要目的是处理状态机之类的事务, 将每个状态封装成为一个单独的类,再借由一个上下文类将所有状态管理起来,每个状态可以借由上下文类切换到其他状态
备忘录模式(快照模式)
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态
个人觉得这个没有什么好聊的,无非就是建立一个管理者类,自己制定好规则,在什么时候将需要备份的类复制进管理者中,在需要的时候拷贝出来就可以完成恢复
访问者模式
有些复杂,还没看懂
中介者模式
该模式提出的设想在于:使用一个中介者来管理所有客户,使得他们能够互相通信,由客户1 改变 客户2 或者客户3 的状态
解除了代码上存在的耦合性
依然抄袭代码,改为模板方式以增加适配性
#include <iostream>
#include <list>
using namespace std;
class Colleague;
//定义一个中介者接口,包含对象改变所需调用函数。
template <class T>
class Mediator
{
public :
virtual ~Mediator()
{
}
virtual void changed(T *)=0;
protected:
std::list<T *> _colleague;
};
//定义"同事"类接口,初始化需要一个中介者对象,并通过该类更新另外一个"同事"
class Colleague
{
public :
//初始化中介者类对象
Colleague(Mediator<Colleague> * mediator)
{
this->mediator =mediator;
}
//更新另外一个类
virtual void changed()
{
mediator->changed(this);
}
virtual void update()=0;
private:
Mediator<Colleague> *mediator;
};
//具体的同事类1
class ConcreteColleague1 :public Colleague
{
public:
ConcreteColleague1(Mediator<Colleague> * mediator):Colleague(mediator)
{
}
void update()
{
cout<<"update ConcreteColleague1 from ConcreteColleague2"<<endl;
}
};
//具体的同事类2
class ConcreteColleague2 :public Colleague
{
public :
ConcreteColleague2(Mediator<Colleague> * mediator):Colleague(mediator)
{
}
void update()
{
cout<<"update ConcreteColleague2 from ConcreteColleague"<<endl;
}
};
//具体的中介者类,实现更新函数changed。
class ConcreteMediator :public Mediator<Colleague>
{
public:
void setColleague(Colleague * colleague)
{
this->_colleague.push_back(colleague);
}
ConcreteMediator()
{
//colleague1 = new ConcreteColleague(this);
}
~ConcreteMediator()
{
}
virtual void changed(Colleague* colleague)
{
for(auto begin=this->_colleague.begin(); begin!=this->_colleague.end(); begin++)
{
if(*begin != colleague)
{
(*begin)->update();
}
}
}
};
main()
{
ConcreteMediator concreteMediator;
ConcreteColleague1 colleague1(&concreteMediator);
ConcreteColleague2 colleague2(&concreteMediator);
concreteMediator.setColleague(&colleague1);
concreteMediator.setColleague(&colleague2);
//"同事1"通过中介者更新"同事2"
colleague1.changed();
//"同事2"通过中介者更新"同事1"
colleague2.changed();
}
解释器模式
这个代码是真不会写,csdn上看到的一些解释器的代码,我不觉得有太高的学习价值。
它主要是一个文本分析器,将语法规则设置进去之后,可以分析一段文本的含义。