简单工厂模式
使用一个单独的类(工厂)来控制其他类的实例化。
实现:制造火车和飞机(一个工厂,一个工厂生产多个产品)
#include "stdafx.h" #include<iostream> #include<string> using namespace std; //抽象产品类 制造的抽象类 拥有纯虚函数的类为抽象类 class Make { public: //纯虚函数 在基类中仅仅给出声明 在派生类中实现 virtual void make() = 0; }; //具体产品类 制造火车的类 继承自制造抽象类 class MakeTrain:public Make { public: void make() { cout << "我可以制造火车!" << endl; } }; //具体产品类 制造飞机的类 继承自制造抽象类 class MakePlane:public Make { public: void make() { cout << "我可以制造飞机!" << endl; } }; //具体工厂类 将客户端和具体的制造类分离 降低耦合度 class Factory { private: MakeTrain train; MakePlane plane; public: void make(string something) { if (something == "train") { train.make(); } else if (something == "plane") { plane.make(); } //用switch更好 但c++不支持switch(string) } }; //客户端 int main() { Factory factory; //客户想要制造什么 只需要告诉工厂就行了 factory.make("train"); factory.make("plane"); return 0; }
类图:(纯虚函数用斜体表示)
优点:工厂类中包含了必要的逻辑判断,可以根据用户的需求动态实例化相关的类;对客户端来说,去除了与具体产品的依赖。
缺点:违背开放-封闭原则,添加新的产品时需要修改工厂类的内容。(解决方案:java可以利用反射技术来代替switch)
工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
实现:制造火车和飞机(多个工厂,一个工厂产生一个产品)
#include "stdafx.h" #include<iostream> #include<string> using namespace std; //抽象产品类 制造类 class Make { public: virtual void make() = 0; }; //具体产品类 制造火车类 class MakeTrain :public Make { public: void make() { cout << "我可以制造火车!" << endl; } }; //具体产品类 制造飞机类 class MakePlane :public Make { public: void make() { cout << "我可以制造飞机!" << endl; } }; //抽象工厂类 class AbstractFactory { public: //返回具体产品类的指针 virtual Make* createProduct() = 0; }; //具体工厂类 制造火车的工厂 class TrainFactory :public AbstractFactory { public: Make * createProduct() { Make* train = new MakeTrain(); return train; } }; //具体工厂类 制造飞机的工厂 class PlaneFactory :public AbstractFactory { public: Make * createProduct() { Make* plane = new MakePlane(); return plane; } }; //客户端代码 int main() { //制造火车 AbstractFactory * factory = new TrainFactory(); Make *product = factory->createProduct(); product->make(); //制造飞机 factory = new PlaneFactory(); product = factory->createProduct(); product->make(); delete factory; delete product; return 0; }
类图:
优点:克服了简单工厂违背开放-封闭原则的缺点。
缺点:每增加一个产品,需要多增加一个对应工厂的类,增加了额外的开发量。
抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
实现:分别为火车和飞机制造发动机和轮胎,火车和飞机用不同的发动机和轮胎。(多个工厂,一个工厂可以产生多个产品)
#include "stdafx.h" #include<iostream> using namespace std; //抽象产品 发动机 class Engine { public: virtual void makeEngine() = 0; }; //具体产品 火车发动机 class TrainEngine :public Engine { public: void makeEngine() { cout << "我可以制造火车发动机!" << endl; } }; //具体产品 飞机发动机 class PlaneEngine :public Engine { public: void makeEngine() { cout << "我可以制造飞机发动机!" << endl; } }; //抽象产品 轮胎 class Tyre { public: virtual void makeTyre() = 0; }; //具体产品 火车轮胎 class TrainTyre :public Tyre { public: void makeTyre() { cout << "我可以制造火车轮胎!" << endl; } }; //具体产品 飞机轮胎 class PlaneTyre :public Tyre { public: void makeTyre() { cout << "我可以执照飞机轮胎!" << endl; } }; //抽象工厂 class AbstractFactory { public: virtual Engine* cerateEngine() = 0; virtual Tyre* createTyre() = 0; }; //具体工厂 火车工厂 class TrainFactory :public AbstractFactory { Engine* cerateEngine() { Engine* trainEngine = new TrainEngine(); return trainEngine; } Tyre* createTyre() { Tyre* trainTyre = new TrainTyre(); return trainTyre; } }; //具体工厂 飞机工厂 class PlaneFactory :public AbstractFactory { Engine* cerateEngine() { Engine* planeEngine = new PlaneEngine(); return planeEngine; } Tyre* createTyre() { Tyre* planeTyre = new PlaneTyre(); return planeTyre; } }; //客户端 int main() { //火车 AbstractFactory* factory = new TrainFactory(); Engine* engine = factory->cerateEngine(); Tyre* tyre = factory->createTyre(); engine->makeEngine(); tyre->makeTyre(); //飞机 factory = new PlaneFactory(); engine = factory->cerateEngine(); tyre = factory->createTyre(); engine->makeEngine(); tyre->makeTyre(); delete factory; delete engine; delete tyre; return 0; }
类图:
优点:需求改变时改动最小;具体的创建实例过程与客户端分离,客户端通过抽象接口操作实例,产品的具体类名也被具体工厂的实现分离,不出现在客户端代码中(客户端只知道有一个抽象工厂,一个抽象的Engine和一个抽象的Tyre)。
缺点;新增功能时,比如火车和飞机都有窗户,那就要增加3个类,还要修改2个具体的工厂类。