工厂方法模式

之前学习的简单工厂模式的最大缺点就是当有新产品加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这违背了“开闭原则”。可以对系统进行修改:不再设计一个工厂类来统一负责所有产品的创建,而是将具体产品的创建过程交给专门的工厂子类去完成。

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生产具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

工厂方法模式的结构

工厂方法模式的结构如图:

从图中可以看出,每一种具体产品都对应了一个具体工厂,所以在代码里只需要指定一个具体工厂就能完成具体产品的创建,从而消除了具体产品的判断逻辑

再以支付方式的案例为例,根据工厂方法模式,代码可以该写为:

  1. class AbstractPay
  2. {
  3. public:
  4.     virtual void pay() = 0;
  5. };
  6.  
  7. class CashPay : public AbstractPay
  8. {
  9. public:
  10.     void pay()
  11.     {
  12.          // 现金支付处理代码
  13.     }
  14. };
  15.  
  16. class CreditcardPay : public AbstractPay
  17. {
  18. public:
  19.     void pay()
  20.     {
  21.          // 信用卡支付处理代码
  22.     }
  23. };
  24.  
  25. class PayMethodFactory
  26. {
  27. public:
  28.     virtual AbstractPay* getPayMethod() = 0;
  29. };
  30.  
  31. class CashPayFactory : public PayMethodFactory
  32. {
  33. public:
  34.     AbstractPay* getPayMethod()
  35.     {
  36.          return new CashPay();
  37.     }
  38. };
  39.  
  40. int main()
  41. {
  42.     PayMethodFactory* factory = new CashPayFactory();
  43.     AbstractPay* payMethod = factory->getPayMethod();
  44.     payMethod->pay();
  45. }

工厂方法模式的应用

在Java集合框架中,常用的List和Set等集合都继承了java.util.Collection接口,在Collection接口中为所有的Java集合类定义了一个iterator()方法,可返回一个用于遍历集合的Iterator类型的对象。而具体的Java集合类可以通过实现该iterator()方法返回一个具体的Iterator对象,该iterator()方法就是工厂方法。

从图中可以看到,此处可以把Collection类当成抽象工厂类,iterator()是工厂方法;Iterator是产品抽象类,衍生出List等具体产品类。每个继承Collection接口的类必须实现其iterator()方法,相当于一个每个产品类对应一个工厂类。

附加的这个例子我觉得很好,它乍一看辨别不出使用了工厂方法模式,能引起一些思考。让人意识到分析的过程相当灵活,使用工厂模式的类的类名中不一定就要附带Factory。