设计模式有 6 大设计原则
- 单一职责原则:基于一个类而言,应该只有一个引起它变化的原因。
- 开放封闭原则:软件实体可以扩展,但不能修改。即面对需求,对程序的改动可以通过增加代码来完成,但不能通过修改现有代码。
- 里氏代换原则:一个软件实体如果使用的是一个基类,那么一定适用于其派生类。即在软件中,把基类替换成派生类,程序的行为没有变化。
- 依赖倒转原则:抽象不应该依赖细节,细节应该依赖抽象。即针对接口编程,而不是针对实现编程。
- 迪米特原则:如果两个类不直接通信,那么这两个类就不应当发生直接关系。如果一个类要调用另一个类中的某个方法,可以通过第三个类转发这个调用。
- 接口隔离原则:每个接口不存在派生类中用不到却必须实现的方法,如若不然,则将接口拆分,使用多个隔离的接口。
设计模式分为三类
- 创造型模式:单例模式、工厂模式、建造者模式、原型模式
- 结构性模式:适配器模式、桥接模式、外观模式、组合模式、装饰模式、享元模式、代理模式
- 行为型模式:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式
下面介绍常见的几种设计模式:
-
单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
-
工厂模式:包括简单工厂模式、抽象工厂模式和工厂方法模式
- 简单工厂模式:主要用于创建对象。用一个工厂来根据输入条件产生不同的类,然后通过不同类的虚函数得到不同的结果。
应用场景: 适用于针对不同情况创建不同类时,只需传入工厂类的参数即可,无需了解具体实现方法。例如:计算器中对于同样的输入,执行不同的操作:加、减、乘、除。
#include <iostream> #include <vector> using namespace std; // Here is the product class class Operation { public: int var1, var2; virtual double GetResult() { double res = 0; return res; } }; class Add_Operation : public Operation { public: virtual double GetResult() { return var1 + var2; } }; class Sub_Operation : public Operation { public: virtual double GetResult() { return var1 - var2; } }; class Mul_Operation : public Operation { public: virtual double GetResult() { return var1 * var2; } }; class Div_Operation : public Operation { public: virtual double GetResult() { return var1 / var2; } }; // Here is the Factory class class Factory { public: static Operation *CreateProduct(char op) { switch (op) { case '+': return new Add_Operation(); case '-': return new Sub_Operation(); case '*': return new Mul_Operation(); case '/': return new Div_Operation(); default: return new Add_Operation(); } } }; int main() { int a, b; cin >> a >> b; Operation *p = Factory::CreateProduct('+'); p->var1 = a; p->var2 = b; cout << p->GetResult() << endl; p = Factory::CreateProduct('*'); p->var1 = a; p->var2 = b; cout << p->GetResult() << endl; return 0; }
- 抽象工厂模式:定义了一个创建一系列相关或相互依赖的接口,而无需指定他们的具体类。
应用场景:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的
产品等级结构。
#include <iostream> #include <vector> using namespace std; // Here is the product class class Operation_Pos { public: int var1, var2; virtual double GetResult() { double res = 0; return res; } }; class Add_Operation_Pos : public Operation_Pos { public: virtual double GetResult() { return var1 + var2; } }; class Sub_Operation_Pos : public Operation_Pos { public: virtual double GetResult() { return var1 - var2; } }; class Mul_Operation_Pos : public Operation_Pos { public: virtual double GetResult() { return var1 * var2; } }; class Div_Operation_Pos : public Operation_Pos { public: virtual double GetResult() { return var1 / var2; } }; /*********************************************************************************/ class Operation_Neg { public: int var1, var2; virtual double GetResult() { double res = 0; return res; } }; class Add_Operation_Neg : public Operation_Neg { public: virtual double GetResult() { return -(var1 + var2); } }; class Sub_Operation_Neg : public Operation_Neg { public: virtual double GetResult() { return -(var1 - var2); } }; class Mul_Operation_Neg : public Operation_Neg { public: virtual double GetResult() { return -(var1 * var2); } }; class Div_Operation_Neg : public Operation_Neg { public: virtual double GetResult() { return -(var1 / var2); } }; /*****************************************************************************************************/ // Here is the Factory class class Factory { public: virtual Operation_Pos *CreateProduct_Pos() = 0; virtual Operation_Neg *CreateProduct_Neg() = 0; }; class Add_Factory : public Factory { public: Operation_Pos *CreateProduct_Pos() { return new Add_Operation_Pos(); } Operation_Neg *CreateProduct_Neg() { return new Add_Operation_Neg(); } }; class Sub_Factory : public Factory { public: Operation_Pos *CreateProduct_Pos() { return new Sub_Operation_Pos(); } Operation_Neg *CreateProduct_Neg() { return new Sub_Operation_Neg(); } }; class Mul_Factory : public Factory { public: Operation_Pos *CreateProduct_Pos() { return new Mul_Operation_Pos(); } Operation_Neg *CreateProduct_Neg() { return new Mul_Operation_Neg(); } }; class Div_Factory : public Factory { public: Operation_Pos *CreateProduct_Pos() { return new Div_Operation_Pos(); } Operation_Neg *CreateProduct_Neg() { return new Div_Operation_Neg(); } }; int main() { int a, b; cin >> a >> b; Add_Factory *p_fac = new Add_Factory(); Operation_Pos *p_pro = p_fac->CreateProduct_Pos(); p_pro->var1 = a; p_pro->var2 = b; cout << p_pro->GetResult() << endl; Add_Factory *p_fac1 = new Add_Factory(); Operation_Neg *p_pro1 = p_fac1->CreateProduct_Neg(); p_pro1->var1 = a; p_pro1->var2 = b; cout << p_pro1->GetResult() << endl; return 0; }
- 工厂方法模式:修正了简单工厂模式中不遵守开放封闭原则。把选择判断移到了客户端去实现,如果想添加新功能就不用修改原来的类,直接修改客户端即可。
应用场景:
- 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
- 一个类通过其派生类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其派生类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,派生类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂派生类中的某一个,客户端在使用时可以无须关心是哪一个工厂派生类创建产品派生类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
#include <iostream> #include <vector> using namespace std; // Here is the product class class Operation { public: int var1, var2; virtual double GetResult() { double res = 0; return res; } }; class Add_Operation : public Operation { public: virtual double GetResult() { return var1 + var2; } }; class Sub_Operation : public Operation { public: virtual double GetResult() { return var1 - var2; } }; class Mul_Operation : public Operation { public: virtual double GetResult() { return var1 * var2; } }; class Div_Operation : public Operation { public: virtual double GetResult() { return var1 / var2; } }; class Factory { public: virtual Operation *CreateProduct() = 0; }; class Add_Factory : public Factory { public: Operation *CreateProduct() { return new Add_Operation(); } }; class Sub_Factory : public Factory { public: Operation *CreateProduct() { return new Sub_Operation(); } }; class Mul_Factory : public Factory { public: Operation *CreateProduct() { return new Mul_Operation(); } }; class Div_Factory : public Factory { public: Operation *CreateProduct() { return new Div_Operation(); } }; int main() { int a, b; cin >> a >> b; Add_Factory *p_fac = new Add_Factory(); Operation *p_pro = p_fac->CreateProduct(); p_pro->var1 = a; p_pro->var2 = b; cout << p_pro->GetResult() << endl; Mul_Factory *p_fac1 = new Mul_Factory(); Operation *p_pro1 = p_fac1->CreateProduct(); p_pro1->var1 = a; p_pro1->var2 = b; cout << p_pro1->GetResult() << endl; return 0; }
- 简单工厂模式:主要用于创建对象。用一个工厂来根据输入条件产生不同的类,然后通过不同类的虚函数得到不同的结果。
-
装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比派生类类更灵活。
-
观察者模式:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,主题对象发生变化时,会通知所有的观察者,使他们能够更新自己。
观察者模式中存在两种角色:- 观察者:内部包含被观察者对象,当被观察者对象的状态发生变化时,更新自己的状态。(接收通知更新状态)
- 被观察者:内部包含了所有观察者对象,当状态发生变化时通知所有的观察者更新自己的状态。(发送通知)
应用场景:
- 当一个对象的改变需要同时改变其他对象,且不知道具体有多少对象有待改变时,应该考虑使用观察者模式;
- 一个抽象模型有两个方面,其中一方面依赖于另一方面,这时可以用观察者模式将这两者封装在独立的对象中使它们各自独立地改变和复用。
#include <iostream> #include <string> #include <list> using namespace std; class Subject; //观察者 基类 (内部实例化了被观察者的对象sub) class Observer { protected: string name; Subject *sub; public: Observer(string name, Subject *sub) { this->name = name; this->sub = sub; } virtual void update() = 0; }; class StockObserver : public Observer { public: StockObserver(string name, Subject *sub) : Observer(name, sub) { } void update(); }; class NBAObserver : public Observer { public: NBAObserver(string name, Subject *sub) : Observer(name, sub) { } void update(); }; //被观察者 基类 (内部存放了所有的观察者对象,以便状态发生变化时,给观察者发通知) class Subject { protected: list<Observer *> observers; public: string action; //被观察者对象的状态 virtual void attach(Observer *) = 0; virtual void detach(Observer *) = 0; virtual void notify() = 0; }; class Secretary : public Subject { void attach(Observer *observer) { observers.push_back(observer); } void detach(Observer *observer) { list<Observer *>::iterator iter = observers.begin(); while (iter != observers.end()) { if ((*iter) == observer) { observers.erase(iter); return; } ++iter; } } void notify() { list<Observer *>::iterator iter = observers.begin(); while (iter != observers.end()) { (*iter)->update(); ++iter; } } }; void StockObserver::update() { cout << name << " 收到消息:" << sub->action << endl; if (sub->action == "梁所长来了!") { cout << "我马上关闭股票,装做很认真工作的样子!" << endl; } } void NBAObserver::update() { cout << name << " 收到消息:" << sub->action << endl; if (sub->action == "梁所长来了!") { cout << "我马上关闭NBA,装做很认真工作的样子!" << endl; } } int main() { Subject *dwq = new Secretary(); Observer *xs = new NBAObserver("xiaoshuai", dwq); Observer *zy = new NBAObserver("zouyue", dwq); Observer *lm = new StockObserver("limin", dwq); dwq->attach(xs); dwq->attach(zy); dwq->attach(lm); dwq->action = "去吃饭了!"; dwq->notify(); cout << endl; dwq->action = "梁所长来了!"; dwq->notify(); return 0; }