赞
踩
典型模式:Factory Method、Abstract Factory、Prototype、Builder
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。
——《设计模式》GoF
class IProduct{ string name; public: virtual void run() = 0; virtual ~IProduct(){} }; class ProductA: public IProduct{ virtual void run(){ //... } }; class ProductB: public IProduct{ virtual void run(){ //... } }; class IFactory{ public: virtual IProduct * createProduct() = 0; virtual ~IFactory(){} }; class ProductAFactory : public IFactory{ public: virtual IProduct * createProduct() { return new ProductA(); } }; class ProductBFactory : public IFactory{ public: virtual IProduct * createProduct() { return new ProductB(); } };
Factory Method模式封装了对象的创建工作,从而避免了客户程序的new操作,只需调用工厂方法即可,解决了客户程序和调用对象之间的紧耦合。
提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
——《设计模式》GoF
// 假设产品A实现x和产品B只能和对应的实现x搭配,不匹配就会产生错误 // 产品A基类 class IProductA{ string name; public: virtual void run() = 0; virtual ~IProductA(){} }; // 产品A实现1 class ProductA1: public IProductA{ virtual void run(){ //... } }; // 产品A实现2 class ProductA2: public IProductA{ virtual void run(){ //... } }; // 产品B基类 class IProductB{ string name; public: virtual void run() = 0; virtual ~IProductB(){} }; // 产品B实现1 class ProductB1: public IProductB{ virtual void run(){ //... } }; // 产品B实现2 class ProductB2: public IProductB{ virtual void run(){ //... } }; // 工厂基类 class IProductFactory{ public: virtual IProductA * createProductA() = 0; virtual IProductB * createProductB() = 0; virtual ~IProductFactory(){} }; // 工厂1:生产产品实现1 class ProductBFactory1 :public IProductFactory{ public: virtual IProductA * createProductA() { return new ProductA1(); } virtual IProductB * createProductB() { return new ProductB1(); } }; // 工厂2:生产产品实现2 class ProductBFactory2 :public IProductFactory{ public: virtual IProductA * createProductA() { return new ProductA2(); } virtual IProductB * createProductB() { return new ProductB2(); } }; int main(int argc, char const *argv[]){ // 新建一类产品 IProductFactory pf1 = new ProductBFactory1; IProductA = pf1.createProductA(); IProductB = pf1.createProductB(); return 0; }
Abstract Factory其实和Factory Method模式类似,只不过他将一系列关联性非常强的对象创建工作封装到了一个类中,这样可以一定程度上避免客户程序创建不匹配的对象进行操作。
使用原型实例(仅供克隆)指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
——《设计模式》GoF
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-efVMMPAA-1664189552211)(http://qny.cwnest.top/designPattern/原型模式类图.png)]
// 抽象类 class ISplitter{ public: virtual ISplitter* clone()=0;//通过克隆自己来创建对象 virtual ~ISplitter(){} }; // 具体类 class BinarySplitter : public ISplitter{ public: virtual ISplitter* clone(){ // C++调用拷贝构造函数,其他语言实现方式可能不同 // 需要实现深拷贝 return new BinarySplitter(*this); } }; class TxtSplitter : public ISplitter{ public: virtual ISplitter* clone(){ return new TxtSplitter(*this); } }; class MainForm : public Form { ISplitter* prototype;//原型对象 public: MainForm(SplitterFactory* prototype){ this->prototype=prototype; } void Button1_Click(){ ISplitter * splitter = prototype->clone();//克隆原型 splitter->split();//使用克隆对象进行操作 } };
原型模式一般来说使用场景较少,适用于工厂方法创建对象比较复杂繁琐的情况,它利用已经处于某种状态的原型对象克隆出新的对象,从而避免了复杂的创建工作,只需在克隆对象上进行相对少量的操作就能达到目的。
将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。
——《设计模式》GoF
// 房子抽象基类 class House{ //... }; // 房子构建类抽象基类 class HouseBuilder{ public: House *GetResult(){ return pHouse; } virtual ~HouseBuilder() {} protected: House *pHouse; virtual void BuildPart1() = 0; virtual void BuildPart2() = 0; virtual void BuildPart3() = 0; virtual void BuildPart4() = 0; virtual void BuildPart5() = 0; } // 负责House类的创建流程(也可以不单独声明成类,放在HouseBuilder中) class HouseDirector{ HouseBuilder *pHouseBuilder; public: HouseDirector(HouseBuilder *hb){ this->pHouseBuilder = hb; } House *Construct(){ pHouseBuilder->BuildPart1(); for (int i = o; i < 4; i++){ pHouseBuilder->BuildPart2(); } bool flag = pHouseBuilder->BuildPart3(); if (flag){ pHouseBuilder->BuildPart4(); } pHouseBuilder->BuildPart5(); return pHouseBuilder->GetResult(); } }; // 具体实现(石头房子) class StoneHouse : public House { // ... }; class StoneHouseBuilder : public HouseBuilder{ protected: virtual void BuildPart1(){ // pHouse->Part1 = . . ; } virtuat void BuildPart2() {} virtual void BuildPart3() {} virtual void BuildPart4() {} virtual void BuildPart5() {} } int main(){ HouseBuilder stoneHouseBuilder = new StoneHouseBuilder(); HouseDirector houseDirector = new HouseDirector(stoneHouseBuilder); House* house = houseDirector.Construct();//得到石头房子 }
tips:为什么C++中父类对象构造函数调用虚函数不能实现多态?
因为在C++中子类初始化时要先调用父类的构造函数,如果在父类构造函数中调用一个虚函数当然无法调用子类对于父类虚函数的重载实现(因为此时子类还没有创建)。
Builder模式和Template Method模式非常类似。特殊点在于Builder模式实在初始化类的时候拥有稳定的构建方式。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。