定义

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

模式结构

工厂方法模式包含如下角色

  • 抽象产品(Product)工厂方法所创建产品对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
  • 具体产品(ConcreteProduct)实现了抽象产品角色所声明的接口
  • 抽象工厂(Factory
  • 具体工厂(ConcreteFactory)实现了抽象工厂接口的具体类,含有与引用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。

image.png

代码分析

工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责哪一个产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
定义基类工厂,将之前的简单工厂模式工厂类修改为下面这样:

  1. #import <Foundation/Foundation.h>
  2. @class LHCarLicense;
  3. @interface LHCarLicenseFactory : NSObject
  4. /**
  5. * 获取牌照工厂
  6. *
  7. * @param type 牌照类型
  8. *
  9. * @return 返回牌照对象
  10. */
  11. + (LHCarLicense *)createCarLicense;
  12. @end
  13. #import "LHCarLicenseFactory.h"
  14. #import "LHCarLicense.h"
  15. @implementation LHCarLicenseFactory
  16. + (LHCarLicense *)createCarLicense{
  17. return nil;
  18. }
  19. @end

然后派生蓝牌工厂类和黄牌工厂类

  1. #import "LHCarLicenseFactory.h"
  2. @interface LHBlueCarLicenseFactory : LHCarLicenseFactory
  3. @end
  4. #import "LHBlueCarLicenseFactory.h"
  5. #import "LHBlueCarLicense.h"
  6. @implementation LHBlueCarLicenseFactory
  7. + (LHCarLicense *)createCarLicense
  8. {
  9. LHBlueCarLicense *_blueCarLicense = [[LHBlueCarLicense alloc] init];
  10. return _blueCarLicense;
  11. }
  12. @end
  1. #import "LHCarLicenseFactory.h"
  2. @interface LHYellowCarLicenseFactory : LHCarLicenseFactory
  3. @end
  4. #import "LHYellowCarLicenseFactory.h"
  5. #import "LHYellowCarLicense.h"
  6. @implementation LHYellowCarLicenseFactory
  7. + (LHCarLicense *)createCarLicense
  8. {
  9. LHYellowCarLicense *_blueCarLicense = [[LHYellowCarLicense alloc] init];
  10. return _blueCarLicense;
  11. }
  12. @end

ok,这样就把原来耦合的业务逻辑剥离出去了,这样的代码逻辑清晰,层面分明、扩展性也好。客户端调用代码只需做如下修改

  1. #import "ViewController.h"
  2. #import "LHCarLicense.h"
  3. #import "LHCarLicenseFactory.h"
  4. #import "LHBlueCarLicenseFactory.h"
  5. #import "LHYellowCarLicenseFactory.h"
  6. @interface ViewController ()
  7. @end
  8. @implementation ViewController
  9. - (void)viewDidLoad {
  10. [super viewDidLoad];
  11. }
  12. - (void)didReceiveMemoryWarning {
  13. [super didReceiveMemoryWarning];
  14. }
  15. #pragma mark -
  16. #pragma mark Button Event
  17. // 生成蓝色牌照
  18. - (IBAction)btnBlueEvent:(UIButton *)sender {
  19. LHCarLicense *_license = [LHBlueCarLicenseFactory createCarLicense];
  20. _license.city = _txtCity.text ? _txtCity.text : @"京";
  21. _lbLicenseNumber.text = [_license printLicenseNumber];
  22. }
  23. // 生成黄色牌照
  24. - (IBAction)btnYellowEvent:(UIButton *)sender {
  25. LHCarLicense *_license = [LHYellowCarLicenseFactory createCarLicense];
  26. _license.city = _txtCity.text ? _txtCity.text : @"京";
  27. _lbLicenseNumber.text = [_license printLicenseNumber];
  28. }
  29. @end

输出结果依然
image.png

优点

  • 在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。
  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  • 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

    缺点

  • 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。

  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。