首先如果把设计模式分为三个大类,则是
1:创建型模式 对象实例化的模式,创建型模式用于解耦对象的实例化过程
2:结构型模式 把类或对象结合在一起形成一个更大的结构
3:行为型模式 类和对象如何交互,以及划分责任和算法
创建型:有 单例、工厂
结构型:有 适配器模式
行为型:观察者模式
工厂模式简单工厂:一个工厂类根据传入的参量决定创建出哪一种产品类的实例
工厂方法:定义一个创建对象的接口,让子类决定实例化哪个类
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类
某莆田代工鞋厂为 李宁 和 安踏 生产鞋子
#include#include using namespace std; typedef enum Product{ LiNing, Anta }ProductBrand; //抽象产品类 class ShoesBrand{ public: virtual void product() = 0; virtual ~ShoesBrand(){} }; class LiNingShoe : public ShoesBrand{ public: void product(){ cout << "LiNing" << endl; } }; class AntaShoes : public ShoesBrand{ public: void product(){ cout << "Anta" << endl; } }; class ShoesFactory{ public: ShoesBrand* CreateShoes(ProductBrand p){ switch(p){ case LiNing : return new LiNingShoe(); case Anta : return new AntaShoes(); default: return nullptr; } } }; int main(){ ShoesFactory* myfactory = new ShoesFactory(); ShoesBrand* lining = myfactory->CreateShoes(LiNing); if(lining){ lining->product(); } ShoesBrand* anta = myfactory->CreateShoes(Anta); if(anta){ anta->product(); } delete lining; lining = nullptr; delete anta; anta = nullptr; return 0; }
ShoesFactory 是工厂类,是整个系统的核心,ShoesBrand 是抽象产品类,简单工厂模式的缺点就是工厂类中集中了所有的创建逻辑,当要增加一个品牌类时,就需要修改工厂类(ShoesFactory),这就违背了六大准则的 开闭原则。没有良好的扩展性
简单工厂模式 中 最大的缺点是当有新产品要加入系统时,必须要修改工厂类,加入必要的处理逻辑,违背了“开闭原则”。
工厂方法模式的定义:在工厂模式中,工厂父类负责定义创建产品对象的公告接口,而工厂的子类负责生成具体的产品对象,目的是将产品的实例化操作延迟到工厂子类中完成,通过工厂子类来确定究竟应该实例化哪一个具体产品类。
优点:系统的扩展性好,符合“开闭原则”,系统加入新产品的时候,不需要修改抽象工厂和抽象产品提供的接口,只要添加一个具体工厂和具体产品就行,比如现在 鸿星尔克 也想来莆田建厂生产鞋子,那么只要 ** 鸿星尔克** 继承抽象品牌类, 再继承一个抽象工厂类,就可以生产出鸿星尔克的鞋子了。
#includeusing namespace std; class ShoesBrand{ public: virtual void product() = 0; virtual ~ShoesBrand(){} }; class LiNingShoes : public ShoesBrand{ public: void product(){ cout << "LiNing" << endl; } }; class AntaShoes : public ShoesBrand{ public: void product(){ cout << "Anta" << endl; } }; class ERKEShoes : public ShoesBrand{ public: void product(){ cout << "ERKE" << endl; } }; // 抽象工厂类 class ShoesFactory { public: virtual ShoesBrand* CreateShoes() = 0; virtual ~ShoesFactory(){} }; class LiNingFactory : public ShoesFactory{ public: ShoesBrand* CreateShoes(){ return new LiNingShoes(); } }; class AntaFactory : public ShoesFactory{ public: ShoesBrand* CreateShoes(){ return new AntaShoes(); } }; class ERKEFactory : public ShoesFactory{ public: ShoesBrand* CreateShoes(){ return new ERKEShoes(); } }; int main(){ ShoesFactory* liningfactory = new LiNingFactory(); ShoesBrand* liningshoes = liningfactory->CreateShoes(); liningshoes->product(); ShoesFactory* antafactory = new AntaFactory(); ShoesBrand* antashoes = antafactory->CreateShoes(); antashoes->product(); ShoesFactory* erkefactory = new ERKEFactory(); ShoesBrand* erkeshoes = erkefactory->CreateShoes(); erkeshoes->product(); if(liningfactory) delete liningfactory; liningfactory = nullptr; if(liningshoes) delete liningshoes; liningshoes = nullptr; if(antafactory) delete antafactory; antafactory = nullptr; if(antashoes) delete antashoes; antashoes = nullptr; if(erkefactory) delete erkefactory; erkefactory= nullptr; if(erkeshoes) delete erkeshoes; erkeshoes= nullptr; return 0; }
在工厂模式中,每个具体工厂只能生产一种具体的产品,比如李宁的工厂只能生产 驭帅10,现在要生产 衣服 了,所以抽象工厂模式中,一个具体的工厂可以生产多个具体的产品。
#includeusing namespace std; class ShoesBrand{ public: virtual void product() = 0; virtual ~ShoesBrand(){} }; //具体的品牌 class LiNingShoes : public ShoesBrand{ public: void product(){ cout << "LiNingShoes" << endl; } }; // class AntaShoes : public ShoesBrand{ public: void product(){ cout << "AntaShoes" << endl; } }; //抽象衣服类 class ClothesBrand{ public: virtual void product() = 0; virtual ~ClothesBrand(){} }; //具体的品牌 class LiNingClothes : public ClothesBrand{ public: void product(){ cout << "LiNingClothes" << endl; } }; // class AntaClothes : public ClothesBrand{ public: void product(){ cout << "AntaClothes" << endl; } }; // 抽象工厂类 class Factory { public: virtual ShoesBrand* CreateShoes() = 0; virtual ClothesBrand* CreateClothes() = 0; virtual ~Factory(){} }; class LiNingFactory : public Factory{ public: ShoesBrand* CreateShoes(){ return new LiNingShoes(); } ClothesBrand* CreateClothes(){ return new LiNingClothes(); } }; class AntaFactory : public Factory{ public: ShoesBrand* CreateShoes(){ return new AntaShoes(); } ClothesBrand* CreateClothes(){ return new AntaClothes(); } }; int main(){ Factory* liningfactory = new LiNingFactory(); ShoesBrand* liningshoes = liningfactory->CreateShoes(); liningshoes->product(); ClothesBrand* liningclothes = liningfactory->CreateClothes(); liningclothes->product(); Factory* antafactory = new AntaFactory(); ShoesBrand* antashoes = antafactory->CreateShoes(); antashoes->product(); ClothesBrand* antaclothes = antafactory->CreateClothes(); antaclothes->product(); if(liningfactory) delete liningfactory; liningfactory = nullptr; if(liningshoes) delete liningshoes; liningshoes = nullptr; if(liningclothes) delete liningclothes; liningclothes = nullptr; if(antafactory) delete antafactory; antafactory =nullptr; if(antashoes) delete antashoes; antashoes = nullptr; if(antaclothes) delete antaclothes; antaclothes = nullptr; return 0; }
抽象工厂如果只生产一类产品的话,就是工厂方法模式。
观察者模式通常用在游戏中,因为主角角色在地图上走的话,周围的陷阱啊,怪兽啊,就会根据主角走的范围做出一系列的反应,这里我举一个例子,“我” 是被观察者,“妈妈” 和 “ 女儿” 都是观察者
#include#include #include #include using namespace std; //观察者接口 class ObserverInterface{ public: virtual void dosomething() = 0; virtual ~ObserverInterface(){} }; //被观察者接口 class SubjectInterface{ public: virtual void add(ObserverInterface*) = 0; //添加 virtual void remove(ObserverInterface*) = 0; //移除 virtual void notify() = 0; virtual ~SubjectInterface(){} }; // Me 是 被观察者 class Me : public SubjectInterface{ public: void add(ObserverInterface* obr) override { observer.push_back(obr); } void remove(ObserverInterface* obr)override { auto pos = std::find(observer.begin(), observer.end(), obr); if(pos != observer.end()) observer.erase(pos); } void notify() override { for(const auto& obs : observer) obs->dosomething(); } private: std::vector observer; }; //观察者 class Wife : public ObserverInterface{ public: void dosomething() override { std::cout << "开始做饭" << std::endl; } }; //观察者 class Daughter : public ObserverInterface{ public: void dosomething() override { std::cout << "去开门" << std::endl; } }; int main(){ Me me; //被观察者 ObserverInterface* wife = new Wife; ObserverInterface* daughter = new Daughter; //订阅消息 me.add(wife); me.add(daughter); me.notify(); delete wife; delete daughter; }
观察者模式:一个物体的行为的改变导致一个或者多个其他对象的行为也发生改变,比如 “我回家了” ,妈妈和女儿就会做出相应的动作。
定义一个观察者接口,其中有 dosomething() 的虚函数,和虚析构函数,定义一个被观察者接口,其中有添加,移除,提醒(notify) 等虚函数,还有虚析构函数,“我” 是继承了 被观察者 的接口,其中具体实现了 add 、remove 等函数,妈妈、女儿 就可以继承观察者接口,其中重写 dosomething() 函数,用来做出相应的动作。之后对于我这个 “ 被观察者 ” 来说,先把 观察者 add ,再 notify,就可以让 观察者 做出相应的动作。
优点: 降低了耦合关系,建立了触发机制。
适配器模式是将一个接口转换为客户希望的另一个接口,使接口不兼容的那些类可以一起工作,即是 适配者模式,它是属于设计模式三个大分类中的 结构型模式。
考虑最经典的 “方钉和圆孔” 的问题,我们要做的是让方钉适应圆孔。适配器让 方钉 假扮成一个 圆钉,其半径是方钉横截面对角线的一半,即能容纳方钉的最小外接圆的半径。
#include#include #include #include //原钉 客户端接口 class RoundPeg{ public: RoundPeg(){} virtual int get_radius() = 0; }; //方钉 适配者类 即和客户端不兼容的类 class SuqarePeg{ public: explicit SuqarePeg(int w) : width_(w){} int get_width(){ return width_; } private: int width_; }; //方钉适配器 该适配器能让客户端将方钉 放入圆孔中 class SquarePegAdapter : public RoundPeg{ public: explicit SquarePegAdapter(SuqarePeg* sp) : square_peg_(sp){} int get_radius() override{ return square_peg_->get_width() * sqrt(2)/2; } private: SuqarePeg* square_peg_; }; //圆孔 客户端类 class RoundHole{ public: explicit RoundHole(int r) : radius_(r){} int get_radius(){ return radius_; } bool isFit(RoundPeg * rp){ return radius_ >= rp->get_radius(); } private: int radius_; }; int main(){ // 半径为10 的圆孔 RoundHole* hole = new RoundHole(10); // 半径分别为 5 和 20 的大小的方钉 + 它们的适配器 SuqarePeg* samll_square_peg = new SuqarePeg(5); SuqarePeg* large_square_peg = new SuqarePeg(20); SquarePegAdapter* small_square_peg_adapter = new SquarePegAdapter(samll_square_peg); SquarePegAdapter* large_square_peg_adapter = new SquarePegAdapter(large_square_peg); if(hole->isFit(small_square_peg_adapter)){ std::cout << "small square peg fits the hole" << std::endl; }else{ std::cout << "small square peg don't fit the hole" << std::endl; } if (hole->isFit(large_square_peg_adapter)) { std::cout << "large square peg fits the hole" << std::endl; } else { std::cout << "large square peg don't fit the hole" << std::endl; } if(hole) delete hole; hole = nullptr; if(samll_square_peg) delete samll_square_peg; samll_square_peg=nullptr; if(large_square_peg) delete large_square_peg; large_square_peg = nullptr; if(small_square_peg_adapter) delete small_square_peg_adapter; small_square_peg_adapter = nullptr; if(large_square_peg_adapter) delete large_square_peg_adapter; large_square_peg_adapter = nullptr; }
适配器继承了 圆钉 的接口,并且在适配器中里面有方法得到方钉的 “ 半径 ”,在圆孔类中,isFit 的参数是 圆钉的指针,在实际使用中,传入的是适配器指针。适配器指针是由 适配器类 new出来的,参数是 方钉类的指针。
优点:
- 解耦:适配器将两个功能完全解耦,从而达到不需要修改任何一方的原有逻辑的目的
- 提高代码复用性:适配的 两方不需要修改任何逻辑,可以更专注自己本身的业务逻辑,对外提供更通用的功能
- 提高系统的扩展性:可以通过各种适配器,对已有的功能或系统进行适配,让其适应更多的场景,是自己的系统扩展性更高。
缺点:
- 造成系统结构混乱,过多的使用适配器,会造成系统过于庞大且混乱不利于系统维护
单例模式之前博客
C++单例模式



