单一职责原则:
就一个类而言,应该仅有一个引起它变化的原因。 如果一个类承担的职责过多,就等于把这些职责耦合在一起, 一个职责的变化可能会削 弱或者抑制这个类完成其它职责能力。这种耦合会导制脆弱的设计,当变化发生时,设计会 遭受到意想不到的破坏
如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责
开放――封闭原则:
软件实体可以扩展,但是不可修改。即对于扩展是开放的,对于修改是封闭的。面 对需求,对程序的改动是通过增加代码来完成的,而不是改动现有的代码。 当变化发生时,我们就创建抽象来隔离以后发生同类的变化。 开放――封闭原则是面向对象的核心所在。 开发人员应该对程序中呈现出频繁变化 的那部分做出抽象,拒绝对任何部分都刻意抽象及不成熟的抽象
里氏代换原则:
一个软件实体如果使用的是一个父类的话,那么一定适用其子类。而且它察觉不出 父类对象和子类对象的区别。也就是说:在软件里面,把父类替换成子类,程序的行为没有 变化。 子类型必须能够替换掉它们的父类型
依赖倒转原则:
抽象不应该依赖细节,细节应该依赖抽象。即针对接口编程,不要对实现编程。 高层模块不能依赖低层模块,两者都应依赖抽象。 依赖倒转原则是面向对象的标志,用哪种语言编写程序不重要,如果编写时考虑的 是如何针对抽象编程而不是针对细节编程,即程序的所有依赖关系都终止于抽象类或接口。 那就是面向对象设计,反之那就是过程化设计
迪米特法则:
如果两个类不直接通信,那么这两个类就不应当发生直接的相互作用。如果 一个类需要调用另一个类的某个方法的话,可以通过第三个类转发这个调用。 在类的结构设计上,每一个类都应该尽量降低成员的访问权限。 该法则在后面的适配器模式、解释模式等中有强烈的体现
简单工厂模式:
主要用于接口选择。新添加类时,不会影响以前的系统代码。核心思想是用一个工厂来根据输入的条件产生不同的类,然后根据不同类的 virtual 函数得到不同的结果
优点:提高了代码的可拓展性
缺点:1、每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。2、不遵循开放——封闭原则,添加产品类时需要修改工厂类
使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
代码:
1 #include <iostream> 2 using namespace std; 3 4 //抽象基类 5 class Shape { 6 public: 7 virtual void draw() const = 0; 8 virtual ~Shape() = default; 9 }; 10 11 //需要创建实体的类 12 class Rectangle : public Shape { 13 public: 14 void draw() const { 15 cout << "creat a Rectangle!" << endl; 16 } 17 }; 18 19 class Square : public Shape{ 20 public: 21 void draw() const { 22 cout << "creat a Square!" << endl; 23 } 24 25 }; 26 27 class Circle : public Shape{ 28 public: 29 void draw() const { 30 cout << "creat a Circle!" << endl; 31 } 32 }; 33 34 //工厂类 35 class ShapeFactory { 36 public: 37 static Shape* Creat(const string&);//根据string参数来创建想要的类实体 38 //不创建工厂类实体,在用户代码中直接通过域作用符调用该静态成员 39 }; 40 41 Shape* ShapeFactory::Creat(const string &s) { 42 if(s == "Rectangle") return new Rectangle(); 43 if(s == "Square") return new Square(); 44 if(s == "Circle") return new Circle(); 45 } 46 47 int main(void) { 48 //通过工厂类来创建我们想要的类型实体 49 Shape *q1 = ShapeFactory::Creat("Circle"); 50 q1->draw(); 51 Shape *q2 = ShapeFactory::Creat("Rectangle"); 52 q2->draw(); 53 Shape *q3 = ShapeFactory::Creat("Square"); 54 q3->draw(); 55 56 delete q1; 57 delete q2; 58 delete q3; 59 60 // 输出: 61 // creat a Circle! 62 // creat a Rectangle! 63 // creat a Square! 64 65 return 0; 66 }
策略模式:
定义算法家族,分别封装起来,让它们之间可以互相替换,让算法变化,不会影响到用户。根据绑定的动态类型不一样调用不同的算法
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题
策略模式和简单工厂基本相同,但简单工厂模式只能解决对象创建问题,对于经常变动的算法应使用策略模式
代码:
1 #include <iostream> 2 using namespace std; 3 4 //策略基类 5 class Operation{ 6 public: 7 virtual doOperation(const int&, const int&) const = 0; 8 virtual ~Operation() = default; 9 }; 10 11 class AddOperation : public Operation{ 12 public: 13 doOperation(const int &a, const int &b) const { 14 return a + b; 15 } 16 }; 17 18 class SubstractOperation : public Operation{ 19 public: 20 doOperation(const int &a, const int &b) const { 21 return a - b; 22 } 23 }; 24 25 class MultiplyOperation : public Operation{ 26 public: 27 doOperation(const int &a, const int &b) const { 28 return a * b; 29 } 30 }; 31 32 //创建 Context 类 33 class Context{ 34 private: 35 Operation *op; 36 37 public: 38 Context(Operation *tmp) : op(tmp) {} 39 int GetResult(const int &a, const int &b) const { 40 op->doOperation(a, b); 41 } 42 43 ~Context() { 44 delete op; 45 } 46 47 }; 48 49 int main(void) { 50 Context c1(new AddOperation()); 51 Context c2(new SubstractOperation()); 52 Context c3(new MultiplyOperation()); 53 54 //根据绑定的动态类型不一样调用不同的算法 55 cout << c1.GetResult(1, 1) << endl;//2 56 cout << c2.GetResult(1, 1) << endl;//0 57 cout << c3.GetResult(1, 1) << endl;//1 58 59 return 0; 60 }
策略与工厂结合:
同时集合了简单工厂模式的选择接口功能以及策略模式的自由选择算法的功能
1 #include <iostream> 2 using namespace std; 3 4 //策略基类 5 class Operation{ 6 public: 7 virtual doOperation(const int&, const int&) const = 0; 8 virtual ~Operation() = default; 9 }; 10 11 class AddOperation : public Operation{ 12 public: 13 doOperation(const int &a, const int &b) const { 14 return a + b; 15 } 16 }; 17 18 class SubstractOperation : public Operation{ 19 public: 20 doOperation(const int &a, const int &b) const { 21 return a - b; 22 } 23 }; 24 25 class MultiplyOperation : public Operation{ 26 public: 27 doOperation(const int &a, const int &b) const { 28 return a * b; 29 } 30 }; 31 32 //创建 Context 类 33 class Context{ 34 private: 35 Operation *op; 36 37 public: 38 Context(const string &s){ 39 if(s == "AddOperation") op = new AddOperation(); 40 else if(s == "SubstractOperation") op = new SubstractOperation(); 41 else op = new MultiplyOperation(); 42 } 43 int GetResult(const int &a, const int &b) const { 44 op->doOperation(a, b); 45 } 46 47 ~Context() { 48 delete op; 49 } 50 51 }; 52 53 int main(void) { 54 //通过 string 参数选择我们想创建的类 55 Context c1("AddOperation"); 56 Context c2("SubstractOperation"); 57 Context c3("MultiplyOperation"); 58 59 //根据绑定的动态类型不一样调用不同的算法 60 cout << c1.GetResult(1, 1) << endl;//2 61 cout << c2.GetResult(1, 1) << endl;//0 62 cout << c3.GetResult(1, 1) << endl;//1 63 64 return 0; 65 }
装饰器模式:
装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。可以在不想增加很多子类的情况下拓展类的功能
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。可以避免随着扩展功能的增多,子类膨胀的情况
缺点:多层装饰比较复杂
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承
代码:
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 //原对象抽象基类 6 class Cake{ 7 public: 8 Cake() : name("Cake") {} 9 virtual void showCake() = 0; 10 virtual ~Cake() = default; 11 std::string name; 12 }; 13 14 //原对象具体类 15 class ConcreteCake : public Cake{ 16 public: 17 //注意: 继承自基类的成员必须通过基类的默认构造函数或构造函数初始化 18 ConcreteCake() : Cake() {} 19 ~ConcreteCake() = default; 20 void showCake() { 21 cout << name << endl; 22 } 23 }; 24 25 //装饰器抽象基类 26 class CakeDecrator : public Cake{ 27 protected: 28 Cake *pCake; 29 30 public: 31 CakeDecrator(Cake *nCake) : pCake(nCake) {} 32 virtual void showCake() = 0; 33 virtual ~CakeDecrator() = default; 34 }; 35 36 //具体装饰类 37 class CakeDecratorMilk : public CakeDecrator{ 38 public: 39 CakeDecratorMilk(Cake *nCake) : CakeDecrator(nCake) {} 40 void showCake() { 41 name = pCake->name + " Milk"; 42 cout << name << endl; 43 } 44 }; 45 46 class CakeDecratorCholate : public CakeDecrator{ 47 public: 48 CakeDecratorCholate(Cake *nCake) : CakeDecrator(nCake) {} 49 void showCake() { 50 name = pCake->name + " Cholate"; 51 cout << name << endl; 52 } 53 54 }; 55 56 int main(void) { 57 ConcreteCake *cCake = new ConcreteCake(); 58 cCake->showCake(); 59 60 CakeDecratorMilk *mCake = new CakeDecratorMilk(cCake); 61 mCake->showCake(); 62 63 CakeDecratorCholate *hCake = new CakeDecratorCholate(mCake); 64 hCake->showCake(); 65 66 delete cCake; 67 delete mCake; 68 delete hCake; 69 70 return 0; 71 }
代理模式:
为其他对象提供一种代理以控制对这个对象的访问。解决在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
优点: 1、职责清晰。 2、高扩展性。 3、智能化。
缺点: 1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。 2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理
注意事项: 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制
代码:
1 #include <iostream> 2 using namespace std; 3 4 //定义接口 5 class Interface { 6 public: 7 virtual void Request() = 0; 8 }; 9 10 //真实类 11 class RealClass : public Interface{ 12 public: 13 virtual void Request() { 14 cout << "real quest" << endl; 15 } 16 }; 17 18 //代理类 19 class ProxyClass : public Interface{ 20 private: 21 RealClass *rclass; 22 public: 23 virtual void Request() { 24 rclass = new RealClass(); 25 rclass->Request(); 26 delete rclass; 27 } 28 }; 29 30 int main(void) { 31 //看起来我们在访问ProxtClass类,但实际上在访问ProxtClass类 32 ProxyClass *test = new ProxyClass(); 33 test->Request(); 34 return 0; 35 }
工厂方法模式:
修正了简单工厂模式中不遵守开放-封闭原则。
工厂方法模式基本与简单工厂模式差不多,但每次添加一个产品子类都必须在工厂类中添加一个判断分支,这样违背了开放-封闭原则。工厂模式就是为了解
代码:
1 #include <iostream> 2 using namespace std; 3 4 //抽象基类 5 class Shape { 6 public: 7 virtual void draw() const = 0; 8 }; 9 10 //需要创建实体的类 11 class Rectangle : public Shape { 12 public: 13 void draw() const { 14 cout << "creat a Rectangle!" << endl; 15 } 16 }; 17 18 class Square : public Shape{ 19 public: 20 void draw() const { 21 cout << "creat a Square!" << endl; 22 } 23 24 }; 25 26 class Circle : public Shape{ 27 public: 28 void draw() const { 29 cout << "creat a Circle!" << endl; 30 } 31 }; 32 33 //工厂基类 34 class ShapeFactory { 35 public: 36 virtual Shape* Creat() = 0;//根据动态绑定创建想要的类 37 virtual ~ShapeFactory() = default; 38 }; 39 40 //具体工厂类 41 class FactoryCircle : public ShapeFactory{ 42 public: 43 Shape* Creat() { 44 return new Circle(); 45 } 46 }; 47 48 class FactoryRectangle : public ShapeFactory{ 49 public: 50 Shape* Creat() { 51 return new Rectangle(); 52 } 53 }; 54 55 class FactorySquare : public ShapeFactory{ 56 public: 57 Shape* Creat() { 58 return new Square(); 59 } 60 }; 61 62 int main(void) { 63 //通过工厂类来创建我们想要的类型实体 64 ShapeFactory *cnt1 = new FactoryCircle(); 65 ShapeFactory *cnt2 = new FactoryRectangle(); 66 ShapeFactory *cnt3 = new FactorySquare(); 67 Shape *q1 = cnt1->Creat(); 68 q1->draw(); 69 Shape *q2 = cnt2->Creat(); 70 q2->draw(); 71 Shape *q3 = cnt3->Creat(); 72 q3->draw(); 73 74 delete cnt1; 75 delete cnt2; 76 delete cnt3; 77 delete q1; 78 delete q2; 79 delete q3; 80 81 // 输出: 82 // creat a Circle! 83 // creat a Rectangle! 84 // creat a Square! 85 86 return 0; 87 }
原型模式:
原型模式的行为类似于拷贝构造函数,但并不等同于拷贝构造函数。拷贝构造函数生成的新对象只能是类本身。原型模式是描述了一个通用方法(或概念),它不管是如何实现的,而拷贝构造则是描述了一个具体实现方法。
Prototype 的意义在于,你拿到一个 Base* ,它指向某个 Derived 对象,你想克隆出 Derived 对象,但代码中不写出 Derived 的具体类型,因为有很多派生类,不知道 Base 的动态类型是什么,这种情况下你用构造函数是搞不定的
代码:
1 #include <iostream> 2 using namespace std; 3 4 class Prototype { 5 private: 6 string name; 7 8 public: 9 Prototype(string s = "") : name(s) {} 10 virtual ~Prototype() = default; 11 virtual Prototype* Clone() { 12 cout << "clone Prototype" << endl; 13 return new Prototype(*this); 14 } 15 void Show() const{ 16 cout << name << endl; 17 } 18 }; 19 20 class ConcretePrototype1 : public Prototype{ 21 public: 22 ConcretePrototype1(string s = "") : Prototype(s) {} 23 ConcretePrototype1* Clone() override { 24 cout << "clone ConcretePrototype1" << endl; 25 return new ConcretePrototype1(*this); 26 } 27 }; 28 29 class ConcretePrototype2 : public Prototype{ 30 public: 31 ConcretePrototype2(string s = "") : Prototype(s) {} 32 ConcretePrototype2* Clone() override { 33 cout << "clone ConcretePrototype2" << endl; 34 return new ConcretePrototype2(*this); 35 } 36 }; 37 38 class ConcretePrototype3 : public Prototype{ 39 public: 40 ConcretePrototype3(string s = "") : Prototype(s) {} 41 ConcretePrototype3* Clone() override { 42 cout << "clone ConcretePrototype3" << endl; 43 return new ConcretePrototype3(*this); 44 } 45 }; 46 47 int main(void) { 48 Prototype *p1 = new ConcretePrototype1(); 49 //假设我们此时并不知道 p1 的动态类型,显然我们不能使用拷贝构造函数,但我们可以通过原型模型构建一个值等同于p1所指对象的对象 50 Prototype *p2 = p1->Clone();//clone ConcretePrototype1 51 return 0; 52 }
模板方法模式:
定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以再不改变一个算法的结构即可重新定义该算法的某些特定步骤。通过把不变的行为搬移到基类中,去除了子类的重复代码,提供了一个很好的代码复用解决方案
模板方法是将原来不变的行为和可变的行为剥离开,将不变的行为剥离到基类中,由基类提供一个模板方法,模板方法设置了算法的骨架,而各家的各个实现步骤和细节由各个子类具体实现
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。3、重构时,经常使用的方案,将相同的代码抽象到父类,通过钩子函数约束行为
样例1:
1 #include <iostream> 2 using namespace std; 3 4 class Game{ 5 protected: 6 virtual void initialize() const = 0; 7 virtual void startPlay() const = 0; 8 virtual void endPlay() const = 0; 9 10 public: 11 void play() { //模板方法 12 initialize();//初始化游戏 13 startPlay();//开始游戏 14 endPlay();//结束游戏 15 } 16 virtual ~Game() = default; 17 }; 18 19 class Cricket : public Game{ 20 protected: 21 void initialize() const override { 22 cout << "Cricket Game initialize." << endl; 23 } 24 void startPlay() const override { 25 cout << "Cricket Game startPlay." << endl; 26 } 27 void endPlay() const override { 28 cout << "Cricket Game endPlay." << endl; 29 } 30 }; 31 32 class Football : public Game{ 33 protected: 34 void initialize() const override { 35 cout << "Football Game initialize." << endl; 36 } 37 void startPlay() const override { 38 cout << "Football Game startPlay." << endl; 39 } 40 void endPlay() const override { 41 cout << "Football Game endPlay." << endl; 42 } 43 }; 44 45 int main(void) { 46 Game *game1 = new Cricket(); 47 game1->play(); 48 cout << endl; 49 50 Game *game2 = new Football(); 51 game2->play(); 52 53 // 输出: 54 // Cricket Game initialize. 55 // Cricket Game startPlay. 56 // Cricket Game endPlay. 57 58 // Football Game initialize. 59 // Football Game startPlay. 60 // Football Game endPlay. 61 62 return 0; 63 }
样例2:
1 #include <iostream> 2 using namespace std; 3 4 class test{ 5 private: 6 problemOne() const { 7 cout << "1 + 1 = ?" << endl; 8 } 9 problemTwo() const { 10 cout << "1 * 1 = ?" << endl; 11 } 12 13 protected: 14 virtual void studentName() const = 0; 15 virtual void answerOne() const = 0; 16 virtual void answerTwo() const = 0; 17 18 public: 19 doTest() const {//模板方法 20 studentName(); 21 problemOne(); 22 answerOne(); 23 problemTwo(); 24 answerTwo(); 25 } 26 27 virtual ~test() = default; 28 }; 29 30 class XiaoHongTestPaper : public test { 31 protected: 32 void studentName() const override { 33 cout << "XiaoHong" << endl; 34 } 35 void answerOne() const override { 36 cout << "10" << endl; 37 } 38 void answerTwo() const override { 39 cout << "1" << endl; 40 } 41 }; 42 43 class XiaoFangTestPaper : public test { 44 protected: 45 void studentName() const override { 46 cout << "XiaoFang" << endl; 47 } 48 void answerOne() const override { 49 cout << "3" << endl; 50 } 51 void answerTwo() const override { 52 cout << "1" << endl; 53 } 54 }; 55 56 int main(void) { 57 test *student1 = new XiaoFangTestPaper(); 58 student1->doTest(); 59 60 cout << endl; 61 62 test *student2 = new XiaoHongTestPaper(); 63 student2->doTest(); 64 65 // 输出: 66 // XiaoFang 67 // 1 + 1 = ? 68 // 3 69 // 1 * 1 = ? 70 // 1 71 72 // XiaoHong 73 // 1 + 1 = ? 74 // 10 75 // 1 * 1 = ? 76 // 1 77 78 return 0; 79 }
外观模式:
外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性,这个接口使得这一子系统更加容易使用
优点: 1、减少系统相互依赖。 2、提高灵活性。 3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
代码:
1 #include <iostream> 2 using namespace std; 3 4 class SubSys{ 5 public: 6 SubSys() = default; 7 virtual ~SubSys() = default; 8 9 virtual void Method() const = 0; 10 }; 11 12 class SubSysOne : public SubSys { 13 public: 14 void Method() const override { 15 cout << "the first way" << endl; 16 } 17 18 }; 19 20 class SubSysTwo : public SubSys { 21 public: 22 void Method() const override { 23 cout << "the twoth way" << endl; 24 } 25 26 }; 27 28 class SubSysThree : public SubSys { 29 public: 30 void Method() const override { 31 cout << "the Third way" << endl; 32 } 33 34 }; 35 36 //外观类 37 class Facade { 38 private: 39 SubSysOne *sub1; 40 SubSysTwo *sub2; 41 SubSysThree *sub3; 42 43 public: 44 Facade() : sub1(new SubSysOne()), sub2(new SubSysTwo()), sub3(new SubSysThree) {} 45 ~Facade() { 46 delete sub1; 47 delete sub2; 48 delete sub3; 49 } 50 51 void FacadeMethod() const { 52 sub1->Method(); 53 sub2->Method(); 54 sub3->Method(); 55 } 56 57 }; 58 59 int main(void) { 60 Facade test; 61 test.FacadeMethod(); 62 63 // 输出: 64 // the first way 65 // the twoth way 66 // the Third way 67 68 return 0; 69 }
建造者模式:
在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用
代码:
1 #include <iostream> 2 #include <list> 3 using namespace std; 4 5 class Packing; 6 7 //创建一个表示食物条目的接口 8 class Item { 9 public: 10 virtual ~Item() = default; 11 12 virtual string name() = 0; 13 virtual Packing* packing() = 0; 14 virtual float price() = 0; 15 }; 16 17 // 创建一个表示食物包装的接口 18 class Packing { 19 public: 20 virtual ~Packing() = default; 21 22 virtual string pack() = 0; 23 }; 24 25 //创建 Packing 派生类 26 class Wrapper : public Packing { 27 public: 28 string pack() override { 29 return "Wrapper"; 30 } 31 }; 32 33 class Bottle : public Packing { 34 public: 35 string pack() override { 36 return "Bottle"; 37 } 38 }; 39 40 //创建 Item 接口的抽象派生类 41 class Burger : public Item { 42 public: 43 Packing* packing() override { 44 return new Wrapper(); 45 } 46 }; 47 48 class ColdDrink : public Item { 49 public: 50 Packing* packing() override { 51 return new Bottle(); 52 } 53 54 }; 55 56 //创建扩展 Bugger 和 ColdDrink 的实体类 57 class VegBurger : public Burger{ 58 public: 59 float price() override { 60 return 25.0f; 61 } 62 string name() { 63 return "Veg Burger"; 64 } 65 }; 66 67 class ChickenBurge : public Burger { 68 public: 69 float price() override { 70 return 50.5f; 71 } 72 string name() override { 73 return "Chicken Burge"; 74 } 75 76 }; 77 78 class Coke : public ColdDrink { 79 public: 80 float price() override { 81 return 30.0f; 82 } 83 string name() { 84 return "Coke"; 85 } 86 }; 87 88 class Pepsi : public ColdDrink { 89 public: 90 float price() override { 91 return 35.0f; 92 } 93 string name() override { 94 return "Pepsi"; 95 } 96 }; 97 98 //创建一个 Meal 类,带有上面的 Item 对象 99 class Meal { 100 private: 101 list<Item*> items; 102 103 public: 104 void addItem(Item *item) { 105 items.push_back(item); 106 } 107 float getCost() { 108 float cost = 0.0f; 109 for(const auto &indx : items) { 110 cost += indx->price(); 111 } 112 return cost; 113 } 114 void showItems() { 115 for(const auto &indx : items) { 116 cout << "Item: " << indx->name(); 117 cout << ", packing: " << (indx->packing())->pack(); 118 cout << ", price: " << indx->price() << endl; 119 } 120 } 121 122 }; 123 124 //创建一个 MealBuilder 类,实际的 builder 类负责创建 Meal 对象 125 class MealBuilder { 126 public: 127 Meal prepareVegMeal() { 128 Meal meal; 129 meal.addItem(new VegBurger()); 130 meal.addItem(new Coke()); 131 return meal; 132 } 133 Meal prepareNonVegMeal() { 134 Meal meal; 135 meal.addItem(new ChickenBurge()); 136 meal.addItem(new Pepsi()); 137 return meal; 138 } 139 140 }; 141 142 int main(void) { 143 MealBuilder m1; 144 145 Meal vegMeal = m1.prepareVegMeal(); 146 cout << "Veg Meal" << endl; 147 vegMeal.showItems(); 148 cout << "Total cost: " << vegMeal.getCost() << endl; 149 cout << endl; 150 151 Meal nonVegMeal = m1.prepareNonVegMeal(); 152 cout << "Non-Veg Meal" << endl; 153 nonVegMeal.showItems(); 154 cout << "Total cost: " << nonVegMeal.getCost() << endl; 155 156 // 输出: 157 // Veg Meal 158 // Item: Veg Burger, packing: Wrapper, price: 25 159 // Item: Coke, packing: Bottle, price: 30 160 // Total cost: 55 161 162 // Non-Veg Meal 163 // Item: Chicken Burge, packing: Wrapper, price: 50.5 164 // Item: Pepsi, packing: Bottle, price: 35 165 // Total cost: 85.5 166 167 return 0; 168 }
观察者模式:
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
代码:
1 //观察者模式 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 //观察者接口 7 class Observer{ 8 public: 9 virtual void update(string msg) = 0; 10 }; 11 12 //第一个观察者 13 class F_Observer : public Observer{ 14 public: 15 void update(string msg) override { 16 cout << "F_Observer: " << msg << endl; 17 } 18 }; 19 20 //第二个观察者 21 class S_Observer : public Observer{ 22 public: 23 void update(string msg) override { 24 cout << "S_Observer: " << msg << endl; 25 } 26 }; 27 28 //第三个观察者 29 class T_Observer : public Observer{ 30 public: 31 void update(string msg) override { 32 cout << "T_Observer: " << msg << endl; 33 } 34 }; 35 36 //被观察者 37 class subject{ 38 public: 39 void setMsg(string msg) { 40 notifyAll(msg); 41 } 42 43 //订阅 44 void addAttach(Observer *observe) { 45 observes.push_back(observe); 46 } 47 48 private: 49 vector<Observer*> observes;//存储订阅者的状态 50 51 notifyAll(string msg) {//通知所有订阅的观察者 52 for(const auto &indx : observes) { 53 indx->update(msg); 54 } 55 } 56 }; 57 58 int main(void) { 59 F_Observer *f_Observer = new F_Observer(); 60 S_Observer *s_Observer = new S_Observer(); 61 T_Observer *t_Observer = new T_Observer(); 62 63 subject sb; 64 sb.addAttach(f_Observer); 65 sb.addAttach(s_Observer); 66 sb.addAttach(t_Observer); 67 68 sb.setMsg("msg has changed"); 69 70 // 输出: 71 // F_Observer: msg has changed 72 // S_Observer: msg has changed 73 // T_Observer: msg has changed 74 75 return 0; 76 }
抽象工厂模式:
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码
代码:
1 //抽象工厂模式 2 #include <iostream> 3 using namespace std; 4 5 //为形状创建一个接口 6 class Shape{ 7 public: 8 virtual void draw() = 0; 9 }; 10 11 //创建实现形状接口的实体类 12 class Rectangel : public Shape{ 13 public: 14 void draw() override { 15 cout << "inside Rectangel::draw() method." << endl; 16 } 17 }; 18 19 class Square : public Shape{ 20 public: 21 void draw() override { 22 cout << "inside Square::draw() method." << endl; 23 } 24 }; 25 26 class Circle : public Shape { 27 public: 28 void draw() override { 29 cout << "inside Circle::draw() method." << endl; 30 } 31 }; 32 33 //为颜色创建一个接口 34 class Color { 35 public: 36 virtual void fill() = 0; 37 }; 38 39 //实现颜色接口类 40 class Red : public Color{ 41 public: 42 void fill() override { 43 cout << "inside Red::fill() method." << endl; 44 } 45 }; 46 47 class Green : public Color{ 48 public: 49 void fill() override { 50 cout << "inside Green::fill() method." << endl; 51 } 52 }; 53 54 class Blue : public Color{ 55 public: 56 void fill() override { 57 cout << "inside Blue::fill() method." << endl; 58 } 59 }; 60 61 //为Color和Shape创建抽象工厂类来获取工厂类 62 class AbstractFactory { 63 public: 64 virtual Color* getColor(const string &color) = 0; 65 virtual Shape* getShape(const string &shape) = 0; 66 }; 67 68 //实现AbstractFactory的具体工厂类 69 class ShapeFactory : public AbstractFactory { 70 public: 71 Shape* getShape(const string &shape) override { 72 if(shape == "Circle") return new Circle(); 73 else if(shape == "Rectangel") return new Rectangel(); 74 else if(shape == "Square") return new Square(); 75 76 return NULL; 77 } 78 79 Color* getColor(const string &color) override { 80 return NULL; 81 } 82 }; 83 84 class ColorFactory : public AbstractFactory { 85 public: 86 Shape* getShape(const string &shape) override { 87 return NULL; 88 } 89 90 Color* getColor(const string &color) override { 91 if(color == "Red") return new Red(); 92 else if(color == "Blue") return new Blue(); 93 else if(color == "Green") return new Green(); 94 95 return NULL; 96 } 97 }; 98 99 //创建一个工厂生成器类,通过传递形状或颜色信息来获取对应工厂 100 class FactoryProducer { 101 public: 102 static AbstractFactory* getFactory(const string &choice) { 103 if(choice == "Shape") return new ShapeFactory(); 104 else if(choice == "Color") return new ColorFactory(); 105 106 return NULL; 107 } 108 }; 109 110 111 int main(void) { 112 //获取形状工厂 113 AbstractFactory *shape_f = FactoryProducer::getFactory("Shape"); 114 //获取形状为Circle的对象 115 Shape *shape1 = shape_f->getShape("Circle"); 116 //调用Circle的draw方法 117 shape1->draw(); 118 119 //获取形状为Rectangle的对象 120 Shape *shape2 = shape_f->getShape("Rectangel"); 121 //调用Rectangle的draw方法 122 shape2->draw(); 123 124 //获取形状为Square的对象 125 Shape *shape3 = shape_f->getShape("Square"); 126 //调用Square的draw方法 127 shape3->draw(); 128 129 //获取颜色工厂 130 AbstractFactory *color_f = FactoryProducer::getFactory("Color"); 131 //获取颜色为Red的对象 132 Color *col1 = color_f->getColor("Red"); 133 //调用Red的fill方法 134 col1->fill(); 135 136 //获取颜色为Green的对象 137 Color *col2 = color_f->getColor("Green"); 138 //调用Green的fill方法 139 col2->fill(); 140 141 //获取颜色为Blue的对象 142 Color *col3 = color_f->getColor("Blue"); 143 col3->fill(); 144 145 delete shape_f; 146 delete shape1; 147 delete shape2; 148 delete shape3; 149 delete color_f; 150 delete col1; 151 delete col2; 152 delete col3; 153 154 return 0; 155 // 输出: 156 // inside Circle::draw() method. 157 // inside Rectangel::draw() method. 158 // inside Square::draw() method. 159 // inside Red::fill() method. 160 // inside Green::fill() method. 161 // inside Blue::fill() method. 162 }
状态模式:
在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象
代码:
Context.h
1 #include <iostream> 2 3 class State; 4 5 //创建Context类 6 class Context { 7 private: 8 State *sta; 9 10 public: 11 Context() : sta(NULL) {} 12 13 void setState(State *state) { 14 this->sta = state; 15 } 16 17 State* getState() { 18 return sta; 19 } 20 };
Context.cpp
1 #include "Context.h"
状态类及测试代码
1 //状态模式 2 #include <iostream> 3 #include "Context.h" 4 using namespace std; 5 6 //创建一个接口 7 class State { 8 public:; 9 virtual void doAction(Context *cont) = 0; 10 virtual string toString() = 0; 11 }; 12 13 //创建实习接口的具体类 14 class StartState : public State { 15 public: 16 void doAction(Context *cont) override { 17 cout << "player is in start state" << endl; 18 cont->setState(this); 19 } 20 21 string toString() { 22 return "start state"; 23 } 24 }; 25 26 class StopState : public State { 27 public: 28 void doAction(Context *cont) override { 29 cout << "player is in stop state" << endl; 30 // cont->setState(this); 31 } 32 33 string toString() { 34 return "Stop State"; 35 } 36 }; 37 38 //使用 Context 来查看当状态 State 改变时的行为变化 39 40 int main(void) { 41 Context *cnt = new Context(); 42 43 StartState start; 44 start.doAction(cnt); 45 cout << cnt->getState()->toString() << endl; 46 47 StopState stopt; 48 stopt.doAction(cnt); 49 cout << cnt->getState()->toString() << endl; 50 51 delete cnt; 52 53 // 输出: 54 // player is in start state 55 // start state 56 // player is in stop state 57 // start state 58 59 return 0; 60 }
适配器模式:
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡
优点: 1、可以让任何两个没有关联的类一起运行。 2、提高了类的复用。 3、增加了类的透明度。 4、灵活性好。
缺点:过多地使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构
代码:
1 #include <iostream> 2 using namespace std; 3 4 //为媒体播放器和更高级的媒体播放器创建接口 5 class MediaPlayer { 6 public: 7 virtual void play(const string &audioType, const string &fileName) = 0; 8 }; 9 10 class AdvancedMediaPlayer { 11 public: 12 virtual void playVlc(const string &fileName) = 0; 13 virtual void playMp4(const string &fileName) = 0; 14 }; 15 16 //创建实现了AdvancedMediaPlayer接口的实体类 17 class VlcPlayer : public AdvancedMediaPlayer { 18 public: 19 void playVlc(const string &fileName) override { 20 cout << "Playing vlc file. name: " << fileName << endl; 21 } 22 23 void playMp4(const string &fileName) override { 24 //do nothing 25 } 26 }; 27 28 class Mp4Player : public AdvancedMediaPlayer { 29 public: 30 void playVlc(const string &fileName) override { 31 //do nothing 32 } 33 34 void playMp4(const string &fileName) override { 35 cout << "Playing Mp4 file. name: " << fileName << endl; 36 } 37 }; 38 39 //创建MediaPlayer接口的适配器类 40 class MediaAdapter : public MediaPlayer { 41 private: 42 AdvancedMediaPlayer *advanceMusicPlayer; 43 44 public: 45 MediaAdapter(const string &audioType) { 46 if(audioType == "vlc") advanceMusicPlayer = new VlcPlayer(); 47 else if(audioType == "mp4") advanceMusicPlayer = new Mp4Player(); 48 } 49 50 void play(const string &audioType, const string &fileName) override { 51 if(audioType == "vlc") advanceMusicPlayer->playVlc(fileName); 52 else if(audioType == "mp4") advanceMusicPlayer->playMp4(fileName); 53 } 54 55 }; 56 57 //创建MediaPlayer接口的实体类 58 class AudioPlayer : public MediaPlayer { 59 private: 60 MediaAdapter *mediaAdapter; 61 62 public: 63 void play(const string &audioType, const string &fileName) override { 64 //播放mp3音乐文件的内置支持 65 if(audioType == "mp3") cout << "Playing mp3 file. name: " << fileName << endl; 66 //mediaAdapter提供了播放其它音乐格式的支持 67 else if(audioType == "vlc" || audioType == "mp4") { 68 mediaAdapter = new MediaAdapter(audioType); 69 mediaAdapter->play(audioType, fileName); 70 }else cout << "Invalid media. " << audioType << " format not supported" << endl; 71 } 72 }; 73 74 int main(void) { 75 //使用AudioPlayer来播放不同类型的音频格式 76 AudioPlayer *audioPlayer = new AudioPlayer(); 77 78 audioPlayer->play("mp3", "beyond the horizon.mp3"); 79 audioPlayer->play("mp4", "alone.mp4"); 80 audioPlayer->play("vlc", "far far away.vlc"); 81 audioPlayer->play("avi", "mind me.avi"); 82 83 // 输出: 84 // Playing mp3 file. name: beyond the horizon.mp3 85 // Playing Mp4 file. name: alone.mp4 86 // Playing vlc file. name: far far away.vlc 87 // Invalid media. avi format not supported 88 89 delete audioPlayer; 90 91 return 0; 92 }
备忘录模式:
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外 保存这个状态,这样就可以将以后的对象状态恢复到先前保存的状态。 适用于功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众 多属性中的一小部分时 Originator 可以根据保存的 Memo 还原到前一状态
代码:
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 class Memento { 6 private: 7 string state; 8 9 public: 10 Memento(const string &s) : state(s) {} 11 string getState() { 12 return state; 13 } 14 }; 15 16 class Originator { 17 private: 18 string state; 19 20 public: 21 //设置状态 22 void setState(const string &s) { 23 state = s; 24 } 25 26 //返回当前状态 27 string getState() { 28 return state; 29 } 30 31 //保存当前状态到Memento中 32 Memento* saveStateToMemento() { 33 return new Memento(state); 34 } 35 36 //从Memento中取出保存的状态 37 void getStateFromMemento(Memento *m) { 38 state = m->getState(); 39 } 40 }; 41 42 //创建管理者类 43 class CareTaker { 44 private: 45 vector<Memento*> mementolist; 46 47 public: 48 void add(Memento *state) { 49 mementolist.push_back(state); 50 } 51 52 Memento* get(int indx) { 53 return mementolist[indx]; 54 } 55 }; 56 57 int main(void) { 58 Originator ori; 59 CareTaker car; 60 61 ori.setState("State #1");//设置当前状态为State #1 62 ori.setState("State #2");//设置当前状态为State #2(覆盖了前面的状态) 63 64 car.add(ori.saveStateToMemento());//将ori的当前状态保存到Memento中 65 ori.setState("State #3"); 66 car.add(ori.saveStateToMemento()); 67 ori.setState("State #4"); 68 69 cout << "Current State: " << ori.getState() << endl;//取出ori中的当前状态 70 ori.getStateFromMemento(car.get(0)); 71 cout << "first saved State: " << ori.getState() << endl; 72 ori.getStateFromMemento(car.get(1)); 73 cout << "second saved State: " << ori.getState() << endl; 74 75 // 输出: 76 // Current State: State #4 77 // first saved State: State #2 78 // second saved State: State #3 79 80 return 0; 81 }
组合模式:
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式
优点: 1、高层模块调用简单。 2、节点自由增加。
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。
1 //组合模式 2 #include <iostream> 3 #include <sstream> 4 #include <vector> 5 using namespace std; 6 7 //创建Employee类,该类带有Employee对象的列表 8 class Employee { 9 private: 10 string name; 11 string dept; 12 int salary; 13 vector<Employee*> subordinates; 14 15 public: 16 Employee(const string &na, const string &de, int sal) : name(na), dept(de), salary(sal) {} 17 18 void add(Employee *e) { 19 subordinates.push_back(e); 20 } 21 22 void remove(Employee *e) { 23 vector<Employee*>::iterator it = subordinates.begin(); 24 while(it != subordinates.end() && (*it) != e) ++it; 25 if(*it == e) subordinates.erase(it); 26 } 27 28 vector<Employee*> getSubordinates() { 29 return subordinates; 30 } 31 32 string toString() { 33 ostringstream os; 34 os << salary; 35 string ref = ""; 36 ref += name; 37 ref += " "; 38 ref += dept; 39 ref += " "; 40 ref += os.str(); 41 return ref; 42 } 43 }; 44 45 int main(void) { 46 Employee *CEO = new Employee("john", "CEO", 30000); 47 48 Employee *headSales = new Employee("Robert", "Head Sales", 20000); 49 Employee *headMarketing = new Employee("Michel", "Head Marketing", 20000); 50 51 Employee *clerk1 = new Employee("Laura", "Marketing", 10000); 52 Employee *clerk2 = new Employee("Bob","Marketing", 10000); 53 54 Employee *salesExecutive1 = new Employee("Richard","Sales", 10000); 55 Employee *salesExecutive2 = new Employee("Rob","Sales", 10000); 56 57 CEO->add(headSales); 58 CEO->add(headMarketing); 59 60 headSales->add(salesExecutive1); 61 headSales->add(salesExecutive2); 62 63 headMarketing->add(clerk1); 64 headMarketing->add(clerk2); 65 66 cout << CEO->toString() << endl; 67 for(const auto &indx : CEO->getSubordinates()) { 68 cout << indx->toString() << endl; 69 for(const auto &j : indx->getSubordinates()) { 70 cout << j->toString() << endl; 71 } 72 } 73 74 // 输出模式: 75 // john CEO 30000 76 // Robert Head Sales 20000 77 // Richard Sales 10000 78 // Rob Sales 10000 79 // Michel Head Marketing 20000 80 // Laura Marketing 10000 81 // Bob Marketing 10000 82 83 return 0; 84 }
迭代器模式:
提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。可以提供不同的方式来遍历整个整合对象
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性
代码:
1 //迭代器模式 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 //迭代器模板抽象基类 7 template<typename Iter> 8 class Iterator { 9 public: 10 virtual Iter next() = 0; 11 virtual bool hasNext() = 0; 12 }; 13 14 //迭代器模板类 15 template<typename Iter> 16 class ConcreteIterator : public Iterator<Iter> { 17 private: 18 vector<Iter> vec; 19 int cursor = 0; 20 21 public: 22 ConcreteIterator(vector<Iter> v) : vec(v) {} 23 24 bool hasNext() override { 25 if(cursor >= vec.size()) return false; 26 return true; 27 } 28 29 Iter next() override { 30 if(hasNext()) return vec[cursor++]; 31 return nullptr; 32 } 33 }; 34 35 //容器模板抽象基类 36 template<typename Iter> 37 class Aggregate { 38 public: 39 virtual void add(Iter obj) = 0; 40 virtual void remove(Iter obj) = 0; 41 virtual Iterator<Iter>* iterator() = 0; 42 }; 43 44 //容器模板类 45 template<typename Iter> 46 class ConcreteAggregate : public Aggregate<Iter> { 47 private: 48 vector<Iter> vec; 49 50 public: 51 void add(Iter obj) override { 52 vec.push_back(obj); 53 } 54 55 Iterator<Iter>* iterator() override { 56 return new ConcreteIterator<Iter>(vec); 57 } 58 59 void remove(Iter obj) override { 60 auto it = vec.begin(); 61 while(it != vec.end() && (*it) != obj) ++it; 62 if(*it == obj) vec.erase(it); 63 } 64 }; 65 66 int main(void) { 67 Aggregate<string> *ag = new ConcreteAggregate<string>(); 68 ag->add("ge"); 69 ag->add("lou"); 70 ag->add("ting"); 71 ag->add("yu"); 72 73 Iterator<string> *it = ag->iterator(); 74 while(it->hasNext()) { 75 cout << it->next() << endl; 76 } 77 78 return 0; 79 }
单例模式:
http://www.cnblogs.com/geloutingyu/p/8640492.html
桥接模式:
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
通俗点来讲就是,比如我们要画个图形,它有两种属性,颜色和形状。如果使用继承来实现的话是这样的,先定义个图形的抽象基类,然后从图形类中派生出颜色类,再从每个颜色类中都派生出所有的形状。在这种实现中颜色和形状这两个维度不能彼此独立,看起来十分臃肿。
换个角度考虑,我们可以将颜色和形状设计成两个独立的继承体系,然后在形状继承体系中加入一个颜色抽象基类指针(反之也可),然后在使用时我们只要创建形状对象并设置里面的颜色指针即可实现形状和颜色的任意组合。在这种实现中,由前面的三层继承体系变成了两层继承体系,减少了很多重复代码,并且颜色和形状可以独立拓展。
代码:
1 //桥接模式 2 #include <iostream> 3 using namespace std; 4 5 //创建桥接接口 6 class DrawAPI { 7 public: 8 virtual void drawCircle(int radius, int x, int y) = 0; 9 virtual ~DrawAPI() = default; 10 }; 11 12 //创建DrawAPI桥接接口的实体类 13 class RedCircle : public DrawAPI { 14 public: 15 void drawCircle(int radius, int x, int y) override { 16 cout << "Drawing Circle[ color: red, radius: " 17 << radius << ", x: " << x << ", " << y << "]" << endl; 18 } 19 }; 20 21 class GreenCircle : public DrawAPI { 22 public: 23 void drawCircle(int radius, int x, int y) override { 24 cout << "Drawing Circle[ color: green, radius: " 25 << radius << ", x: " << x << ", " << y << "]" << endl; 26 } 27 }; 28 29 //创建Shape抽象基类 30 class Shape { 31 protected: 32 DrawAPI *draw_api; 33 Shape(DrawAPI *draw) : draw_api(draw) {} 34 35 public: 36 virtual void draw() = 0; 37 virtual ~Shape() = default; 38 }; 39 40 //创建Shape的实体类 41 class Circle : public Shape { 42 private: 43 int x, y, radius; 44 45 public: 46 Circle(int a, int b, int rad, DrawAPI *draw) : 47 x(a), y(b), radius(rad), Shape(draw) {} 48 void draw() override { 49 draw_api->drawCircle(radius, x, y); 50 } 51 }; 52 53 int main(void) { 54 Shape *red_c = new Circle(100, 100, 10, new RedCircle()); 55 Shape *green_c = new Circle(100, 100, 10, new GreenCircle()); 56 57 red_c->draw(); 58 green_c->draw(); 59 60 // 输出: 61 // Drawing Circle[ color: red, radius: 10, x: 100, 100] 62 // Drawing Circle[ color: green, radius: 10, x: 100, 100] 63 64 return 0; 65 }
命令模式:
命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
先建一个请求类,请求类中有一系列动作。再建立一个命令类继承体系,并通过请求类来初始化命令类对象,即对不同的指令调用对应的请求类动作。最后建立一个调用指令类即指令队列
代码:
1 //命令模式 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 //创建一个请求类 7 class Stock { 8 private: 9 string name = "abc"; 10 int quantity = 10; 11 12 public: 13 void buy() { 14 cout << "Stock [ Name: " << name << ", Quantity: " 15 << quantity << " ] bought" << endl; 16 } 17 18 void sell() { 19 cout << "Stock [ Name: " << name << ", Quantity: " 20 << quantity << " ] sold" << endl; 21 } 22 }; 23 24 //创建一个命令接口 25 class Oeder { 26 public: 27 virtual void execute() = 0; 28 virtual ~Oeder() = default; 29 }; 30 31 //实现Order接口的实体类 32 class BuyStock : public Oeder { 33 private: 34 Stock abcStock; 35 36 public: 37 BuyStock(Stock abc) : abcStock(abc) {} 38 void execute() override { 39 abcStock.buy(); 40 } 41 }; 42 43 class SellStock : public Oeder { 44 private: 45 Stock abcStock; 46 47 public: 48 SellStock(Stock abc) : abcStock(abc) {} 49 void execute() override { 50 abcStock.sell(); 51 } 52 }; 53 54 //创建调用指令类 55 class Broker { 56 private: 57 vector<Oeder*> vec; 58 59 public: 60 void takeOeder(Oeder *oed) { 61 vec.push_back(oed); 62 } 63 64 void placeOeder() { 65 for(auto indx : vec) { 66 indx->execute(); 67 } 68 } 69 }; 70 71 int main(void) { 72 Stock abcStock; 73 74 BuyStock *buy = new BuyStock(abcStock); 75 SellStock *sell = new SellStock(abcStock); 76 77 Broker bk; 78 bk.takeOeder(buy);//添加命令 79 bk.takeOeder(sell); 80 bk.placeOeder();//通知执行命令 81 82 delete buy; 83 delete sell; 84 85 // 输出: 86 // Stock [ Name: abc, Quantity: 10 ] bought 87 // Stock [ Name: abc, Quantity: 10 ] sold 88 89 return 0; 90 }
责任链模式:
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推
代码:
1 //责任链模式 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 //请求 7 class Request { 8 public: 9 unsigned int n;//表示任务等级,10级以下CommnoManager处理,之上则MajorDomo处理 10 Request(int x) : n(x) {} 11 }; 12 13 //管理者抽象基类 14 class Manager { 15 protected: 16 Manager *manager; 17 string name; 18 19 public: 20 Manager(string temp) : name(temp) {} 21 virtual ~Manager() = default; 22 23 void SetSuccessor(Manager *temp) { 24 manager = temp; 25 } 26 27 virtual void GetRequest(Request req) = 0; 28 }; 29 30 //经理 31 class CommonManager : public Manager { 32 public: 33 CommonManager(string str) : Manager(str) {} 34 35 void GetRequest(Request req) override { 36 if(req.n >= 0 && req.n < 10) { 37 cout << "CommonManager: " << name << " " << req.n << endl; 38 }else manager->GetRequest(req);//经理无法处理,传递给上一级处理 39 } 40 }; 41 42 //总监 43 class MajorDomo : public Manager { 44 public: 45 MajorDomo(string str) : Manager(str) {} 46 47 void GetRequest(Request req) override { 48 cout << "MajorDomo: " << name << " " << req.n << endl; 49 } 50 }; 51 52 int main(void) { 53 Manager *common = new CommonManager("jingli"); 54 Manager *major = new MajorDomo("zongjian"); 55 56 common->SetSuccessor(major); 57 58 Request cnt1(1), cnt2(11); 59 60 common->GetRequest(cnt1); 61 common->GetRequest(cnt2); 62 63 // 输出: 64 // CommonManager: jingli 1 65 // MajorDomo: zongjian 11 66 67 return 0; 68 }
中介者模式:
用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
何时使用:多个类相互耦合,形成了网状结构
如何解决:将上述网状结构分离为星型结构
代码:
1 //中介者模式 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 class Colleague; 7 8 //中介者抽象基类 9 class Mediator { 10 public: 11 virtual void Send(string message, Colleague *col) = 0; 12 virtual ~Mediator() = default; 13 }; 14 15 //同事类的抽象基类 16 class Colleague { 17 protected: 18 Mediator *med; 19 20 public: 21 Colleague(Mediator *m) : med(m) {} 22 virtual ~Colleague() = default; 23 24 virtual void Notify(string str) = 0; 25 26 void Send(string str) { 27 med->Send(str, this); 28 } 29 }; 30 31 //同事一 32 class Colleaguel : public Colleague { 33 public: 34 Colleaguel(Mediator *m) : Colleague(m) {} 35 void Notify(string str) override { 36 cout << "Colleaguel to Colleague2: " << str << endl; 37 } 38 }; 39 40 //同事二 41 class Colleague2 : public Colleague { 42 public: 43 Colleague2(Mediator *m) : Colleague(m) {} 44 void Notify(string str) override { 45 cout << "Colleague2 to Colleaguel: " << str << endl; 46 } 47 }; 48 49 //中介者具体类 50 class ConcreteMediator : public Mediator { 51 public: 52 Colleaguel *col1; 53 Colleague2 *col2; 54 void Send(string message, Colleague *col) override { 55 if(col == col1) col1->Notify(message); 56 else col2->Notify(message); 57 } 58 }; 59 60 int main(void) { 61 //中介 62 ConcreteMediator *m = new ConcreteMediator(); 63 64 //让同事认识中介 65 Colleaguel *col1 = new Colleaguel(m); 66 Colleague2 *col2 = new Colleague2(m); 67 68 // //让中介认识具体的同事类 69 m->col1 = col1; 70 m->col2 = col2; 71 72 col1->Send("do you have lunch?"); 73 col2->Send("no."); 74 75 return 0; 76 }
享元模式:
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象
代码:
1 //享元模式 2 #include <iostream> 3 #include <vector> 4 #include <map> 5 #include <stdlib.h> 6 using namespace std; 7 8 class Shape { 9 public: 10 virtual void draw() = 0; 11 virtual void set_x(int) = 0; 12 virtual void set_y(int) = 0; 13 virtual void set_rad(int) = 0; 14 virtual ~Shape() = default; 15 }; 16 17 class Circle : public Shape { 18 private: 19 string color; 20 int x, y, radius; 21 22 public: 23 Circle(string col) : color(col) {} 24 25 void set_x(int a) override { 26 x = a; 27 } 28 29 void set_y(int b) override { 30 y = b; 31 } 32 33 void set_rad(int c) override { 34 radius = c; 35 } 36 37 void draw() override { 38 cout << "Circle: draw() [Color : " << color 39 << ", x : " << x << ", y :" << y << ", radius :" << radius << endl; 40 } 41 }; 42 43 //创建一个工厂,生成基于给定信息的实体类的对象 44 class ShapeFactory { 45 private: 46 static map<string, Shape*> mp; 47 48 public: 49 static Shape* getCircle(string col) { 50 Shape *cir = mp[col]; 51 if(cir == nullptr) { 52 cir = new Circle(col); 53 mp[col] = cir; 54 } 55 return cir; 56 } 57 }; 58 59 //类静态成员需要在类外声明 60 map<string, Shape*> ShapeFactory::mp; 61 62 int main(void) { 63 string col[] = {"Rfj", "zdf", "fes", "zz"}; 64 65 for(int i = 0; i < 20; ++i) { 66 Shape *cir = ShapeFactory::getCircle(col[rand() % 4]); 67 cir->set_x(rand() % 100); 68 cir->set_y(rand() % 100); 69 cir->set_rad(100); 70 cir->draw(); 71 } 72 73 return 0; 74 }
解释器模式:
解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等
意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子
主要解决:对于一些固定文法构建一个解释句子的解释器
代码:
1 // 解释器模式 2 #include <iostream> 3 using namespace std; 4 5 //创建一个表达式接口 6 class Expression { 7 public: 8 virtual bool interpret(string context) = 0; 9 virtual ~Expression() = default; 10 }; 11 12 class TerminalExpression : public Expression { 13 private: 14 string data; 15 16 public: 17 TerminalExpression(string s) : data(s) {} 18 bool interpret(string context) override { 19 if(context.find(data) != -1) return true; 20 return false; 21 } 22 }; 23 24 class OrExpression : public Expression { 25 private: 26 Expression *expr1 = nullptr; 27 Expression *expr2 = nullptr; 28 29 public: 30 OrExpression(Expression *exp1, Expression *exp2) : 31 expr1(exp1), expr2(exp2) {} 32 33 bool interpret(string context) override { 34 return expr1->interpret(context) || expr2->interpret(context); 35 } 36 }; 37 38 class AndExpression : public Expression { 39 private: 40 Expression *expr1 = nullptr; 41 Expression *expr2 = nullptr; 42 43 public: 44 AndExpression(Expression *exp1, Expression *exp2) : 45 expr1(exp1), expr2(exp2) {} 46 47 bool interpret(string context) override { 48 return expr1->interpret(context) && expr2->interpret(context); 49 } 50 }; 51 52 Expression* getMaleExpression() { 53 //规则:Robert 和 John 是男性 54 Expression *robert = new TerminalExpression("robert"); 55 Expression *john = new TerminalExpression("john"); 56 return new OrExpression(robert, john); 57 } 58 59 Expression* getMarriedWomanExpression() { 60 // 规则:Julie 是一个已婚女性 61 Expression *julie = new TerminalExpression("julie"); 62 Expression *married = new TerminalExpression("married"); 63 return new AndExpression(julie, married); 64 } 65 66 int main(void) { 67 Expression *isMale = getMaleExpression(); 68 Expression *isMarrieWoman = getMarriedWomanExpression(); 69 70 cout << "john is male? " << isMale->interpret("john") << endl; 71 cout << "julie is a married women? " << isMarrieWoman->interpret("married julie") << endl; 72 73 // 输出: 74 // john is male? 1 75 // julie is a married women? 1 76 77 delete isMale; 78 delete isMarrieWoman; 79 80 return 0; 81 }