C++ 学习(3) ----设计模式
创建型模式
创建型模式对类的实例化过程进行了抽象,能够将软件模块中对象的创建和使用相分离;
为了使软件的结构更加清晰,外界对于这些对象只需要知道他们共同的接口,并不清楚具体的实现细节,使得整个系统的设计更加符合单一设计原则
创建型模式包含下面这几个模式
- 简单工厂模式(
Simple Factory
) - 工厂方法模式(
Factory Method
) - 抽象工厂模式(
Abstract Method
) - 建造者模式(
Builder
) - 原型模式(
Prototype
) - 单例模式(
Singleton
)
简单工厂模式
考虑一个简单的场景,一个软件系统可以提供各种外观不同的按钮(圆形按钮,矩阵按钮),这些按钮都源自同一个基类,不过继承基类后不同的子类修改了部分属性从而使它们呈现了不同的外观;
我们希望使用这些按钮的时候,不需要知道具体的按钮的名字,只需要知道表示这个按钮类的一个参数,并且提供一个方便调用的方法,传入参数就可以或者一个具体的对象,这个就是简单工厂模式
实现代码:
#include "Factory.h"
#include "ConcreteProductA.h"
#include "ConcreteProductB.h"Product* Factory::createProduct(string name) {if("A" ==name) {return new ConcreteProductA();} else if ("B" ==name) {return new ConcreteProductB();}return nullptr;
}
简单工厂模式的不足:
- 工厂类中集中了所有产品的创建逻辑,一旦不能正常工作,整个系统都受到影响
- 系统扩展困难,一旦添加新产品就不得不修改工厂的逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护
工厂方法模式
对上面的简单工厂模式进行修改,不再设计一个统一按钮工厂类来负责所有产品的创建,而是将具体的按钮创建过程交给专门的工厂子类完成,先定义一个抽象的按钮工厂类,在定义具体的工厂类来生成圆形按钮,矩形按钮,菱形按钮等等
工厂方法模式也称为(FactoryMethodPattern
)也称为工厂模式,也叫虚拟构造器模式和多态工厂模式,在工厂方法模式中,工厂父类负责创建产品对象的公共接口,而工厂子类负责生成具体的产品对象
实现代码:
#include "ConcreteFactory.h"
#include "ConcreteProduct.h"Product* ConcreteFactory::factoryMethod(){return new ConcreteProduct();
}#include "Factory.h"
#include "ConcreteFactory.h"
#include "Product.h"
#include <iostream>
using namespace std;int main(int argc, char *argv[])
{Factory * fc = new ConcreteFactory();Product * prod = fc->factoryMethod();prod->use();delete fc;delete prod;return 0;
}
工厂方法模式的不足:
添加新产品时,需要编写新的具体产品类,还要添加与之对应的具体的工厂类;一定程度增加了系统的复杂度,有更多类需要编译运行,增加了一些额外的开销
单例模式
单例模式可以保证系统中只存在一个类的实例化对象
单例模式的主要特点:
- 这个类只能有一个实例
- 必须是由类本身创建自己的实例
- 必须向系统提供获取实例的接口
实现代码:
#include <iostream>
#include "Singleton.h"
using namespace std;int main(int argc, char *argv[])
{Singleton * sg = Singleton::getInstance();sg->singletonOperation();return 0;
}#include "Singleton.h"
#include <iostream>
using namespace std;Singleton *Singleton::instance = NULL;Singleton::Singleton(){
}Singleton::~Singleton(){delete instance;
}Singleton* Singleton::getInstance(){if (instance == NULL){instance = new Singleton();}return instance;
}void Singleton::singletonOperation(){cout << "singletonOperation" << endl;
}
结构型模式
结构型模式描述如何将对象或者类结合在一起,形成更加强大的结构
结构型模式包含下面几种:
- 适配器模式(
Adapter
) - 桥接模式(
Bridge
) - 组合模式(
Composite
) - 装饰模式(
Decorator
) - 外观模式(
Facade
) - 享元模式(
Flyweight
) - 代理模式(
Proxy
)
外观模式
外部和一个子系统通信的时候必须通过一个统一的外观对象进行,为子系统中的一组接口提供了一个一致的界面,外观模式定义了一个高层接口,这个接口使得子系统更加容易使用
注意外面模式的统一接口并不是重写基类中的接口,只是定义了一个外观接口
class Facade
{public:Facade();virtual ~Facade();void wrapOpration();private:SystemC *m_SystemC;SystemA *m_SystemA;SystemB *m_SystemB;
};
#endif #include "Facade.h"Facade::Facade(){m_SystemA = new SystemA();m_SystemB = new SystemB();m_SystemC = new SystemC();
}Facade::~Facade(){delete m_SystemA;delete m_SystemB;delete m_SystemC;
}void Facade::wrapOpration(){m_SystemA->operationA();m_SystemB->operationB();m_SystemC->opeartionC();
}
外观模式的缺点:
- 不能很好现象客户使用子系统的类,如果对客户访问子系统做了太多限制则减少了可变性和灵活性
- 在不引入抽象外观类的情况下,增加新的子系统可能会需要修改外观类或者客户端的源代码,违背了开闭原则
行为型模式
行为型模式是在对不同对象之间划分责任和算法的抽象化
行为型模式不仅关注类和对象的结构,而且重点关注它们的相互作用
通过行为型模式,可以更加清晰的划分类和对象的职责,并研究系统在运行时实例对象之间的交互;在系统运行时,对象不是孤立的,它可以通过相互通信和协作完成某些复杂功能,一个对象的运行也会影响其他对象
行为型模式包含下面:
- 职责链模式(
Chain of Responsibility
) - 命令模式(
Command
) - 解释器模式(
Interpreter
) - 迭代器模式(
Iterator
) - 中介者模式(
Mediator
) - 备忘录模式(
Memento
) - 观察者模式(
Observer
) - 状态模式(
State
) - 策略模式(
Strategy
) - 模板方法模式(
Template Method
) - 访问者模式(
Vistor
)
观察者模式
观察者模式建立一种对象之间的依赖关系,一个对象改变时通知其他对象,其他对象做出反应;发生改变的对象称为观察目标,被通知的对象被称为观察者,一个观察目标可以对应多个观察者
观察者模式也称为发布订阅模式,模型视图模式等等
观察目标的代码实现(内部包含了观察者对象)
#include "Obeserver.h"
#include <vector>
using namespace std;class Subject {
public:Subject();virtual ~Subject();Obeserver *m_Obeserver;void attach(Obeserver * pObeserver);void detach(Obeserver * pObeserver);void notify();virtual int getState() = 0;virtual void setState(int i)= 0;private:vector<Obeserver*> m_vtObj;
};
#endif #include "Subject.h"Subject::Subject(){}
Subject::~Subject(){}void Subject::attach(Obeserver * pObeserver){m_vtObj.push_back(pObeserver);
}void Subject::detach(Obeserver * pObeserver){for(vector<Obeserver*>::iterator itr = m_vtObj.begin();itr != m_vtObj.end(); itr++){if(*itr == pObeserver){m_vtObj.erase(itr);return;} }
}void Subject::notify(){for(vector<Obeserver*>::iterator itr = m_vtObj.begin();itr != m_vtObj.end();itr++){ (*itr)->update(this); }
}
观察者的示例代码(注意包含了观察目标的通知接口 update):
#include "Obeserver.h"
#include <string>
using namespace std;class ConcreteObeserver : public Obeserver {
public:ConcreteObeserver(string name);virtual ~ConcreteObeserver();virtual void update(Subject * sub);private:string m_objName;int m_obeserverState;
};#include "ConcreteObeserver.h"
#include <iostream>
#include <vector>
#include "Subject.h"
using namespace std;ConcreteObeserver::ConcreteObeserver(string name){m_objName = name;
}ConcreteObeserver::~ConcreteObeserver() {}void ConcreteObeserver::update(Subject * sub){m_obeserverState = sub->getState();cout << "update oberserver[" << m_objName << "] state:" << m_obeserverState << endl;
}