1.抽象工厂模式简介
在之前的文章设计模式之工厂方法模式中,工厂方法模式可以将产品的创建过程放入具体的工厂类中,每一个工厂可以创建的一个具体产品,由此可能会创建很多个工厂类。
现实生活中,一个工厂可能不仅仅只生产一种产品,而是生产一类产品。比如一个体育用品厂,它可能会生产多种与体育相关的产品。此时,我们可以把这些相关的产品归为一个产品大类,由同一个工厂来生产,这便是抽象工厂模式。
抽象工厂模式定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2.抽象工厂模式结构
抽象工厂模式与工厂方法模式从结构角度来说是相似的,不同之处在于,一个具体工厂可以生产出多个同种类型相关的产品。
抽象工厂:所有生产具体产品的工厂类的基类,提供工厂类的公共方法;
具体工厂:生产具体的产品;
抽象产品:所有具体产品的基类,提供具体产品类的公共方法;
具体产品:具体的产品类;
从上图可以看出,具体工厂ConcreteFactory_A可以生产两种产品ConcreteProduct_A_1和ConcreteProduct_A_2。客户端使用时,需要声明一个抽象工厂AbstractFactory和两个抽象产品AbstractProduct。
3.抽象工厂模式实战
假设有如下一个场景:体育运动爱好者CurryCoder想出门进行户外运动,他可以选择打篮球或者踢足球。但是,此时他还想打篮球或踢足球时同时穿上自己喜欢球员的球衣。篮球保管室可以提供篮球和篮球服,足球保管室也可以提供足球和足球服。CurryCoder只需要到对应的保管室申请对应的球和球衣就可以出门运动了。
#include <iostream> using namespace std; // 抽象产品类AbstractBall class AbstractBall { public: AbstractBall(){ } // 公有方法: void play(){ } }; // 具体产品类 class Basketball: public AbstractBall{ public: Basketball(){ play(); } void play(){ cout << "CurryCoder正在打篮球\n"; } }; class Football: public AbstractBall{ public: Football(){ play(); } void play(){ cout << "CurryCoder正在踢足球\n"; } }; // 抽象产品类AbstractShirt class AbstractShirt{ public: AbstractShirt(){ } // 公有方法 void wearShirt(){ } }; // 具体产品类 class BasketballShirt: public AbstractShirt{ public: BasketballShirt(){ wearShirt(); } void wearShirt(){ cout << "CurryCoder穿上库里的篮球衣啦\n"; } }; class FootballShirt: public AbstractShirt{ public: FootballShirt(){ wearShirt(); } void wearShirt(){ cout << "CurryCoder穿上C罗的足球衣啦\n"; } }; // 定义抽象工厂AbstractFactory class AbstractFactory{ public: virtual AbstractBall* getBall() = 0; virtual AbstractShirt* getShirt() = 0; }; // 定义具体工厂BasketballFactory class BasketballFactory: public AbstractFactory{ public: BasketballFactory(){ cout << "Basketball Factory\n"; } AbstractBall* getBall(){ cout << "CurryCoder得到篮球一个\n"; return new Basketball(); } AbstractShirt* getShirt(){ cout << "CurryCoder得到篮球衣一件\n"; return new BasketballShirt(); } }; // 定义具体工厂FootballFactory class FootballFactory: public AbstractFactory{ public: FootballFactory(){ cout << "Football Factory\n"; } AbstractBall* getBall(){ cout << "CurryCoder得到足球一个\n"; return new Football(); } AbstractShirt* getShirt(){ cout << "CurryCoder得到足球衣一件\n"; return new FootballShirt(); } }; // 客户端程序 int main(){ // 定义工厂类对象 AbstractFactory* fac = nullptr; // 定义产品类对象 AbstractBall* ball = nullptr; AbstractShirt* shirt = nullptr; fac = new BasketballFactory(); ball = fac->getBall(); shirt = fac->getShirt(); cout << "======================我是完美分隔线====================\n"; fac = new FootballFactory(); ball = fac->getBall(); shirt = fac->getShirt(); return 0; }
4.抽象工厂模式总结
抽象工厂模式中,如果需要新增一个系列的产品(例如增加排球这个产品大类),只需增加一个新的产品大类(具体产品和抽象产品类)并提供一个对应的工厂类即可。但是,如果要在已有的产品大类中增加另一个新产品,比如CurryCoder打篮球,除了需要篮球和篮球衣外,还想换双篮球鞋,这时候该怎么办呢?是不是要去修改BasketballFactory呢?因此,本文总结了抽象工厂模式的特点:
优点:
(1).抽象工厂模式用于创建客户所需的具体产品,同时向客户隐藏某个具体产品类将被实例化的细节,用户只需关心所需产品对应的工厂;
(2).加入新的产品大类时,无需修改原有系统,增强了系统的可扩展性,符合开闭原则。
缺点:
如果要在已有产品大类中添加新产品时,需要修改抽象层代码,对原有系统改动较大,违背开闭原则。