工厂模式(Factory Pattern):解决对象创建问题,将对象的创建和使用解藕。
1 介绍
工厂模式(Factory Pattern),顾名思义就是我们可以通过一个指定的“工厂”获得需要的“产品”,在设计模式中主要用于抽象对象的创建过程,让用户可以指定自己想要的对象而不必关心对象的实例化过程。这样做的好处是用户只需通过固定的接口而不是直接去调用类的实例化方法来获得一个对象的实例,隐藏了实例创建过程的复杂度,解耦了生产实例和使用实例的代码,降低了维护的复杂性。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。所谓的“创建逻辑”是指我必须要知道创建函数的构造函数的逻辑组成,才能创建对象。
在工厂方法模式中,父类负责定义创建对象的公共接口,而子类则负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成,即由子类来决定究竟应该实体化哪一个类。
例如:
class Car(object):
def __init__(self, brand, car_type, config_type):
self.brand = brand
self.car_type = car_type
self.config_type = config_type
car = Car("BMW", "X1", "Full")
在上面的例子中,要想创建一个car实例对象,我们需要知道车的品牌,型号,配置等一系列信息。车的配置信息很多,除此之外,我们还需要其他大量信息,例如车架号,发动机编号等一系列数据。那有没有办法在不知道这些信息的情况下创建一个car实例呢?这就是工厂模式要做的事情。
所谓”工厂模式“就是专门提供一个”工厂类“去创建对象,我只需要告诉这个工厂我需要什么,它就会返回给我一个相对应的对象。说的更通俗一点,就是专门创建类型的实例的工厂(类) 。
2 适用场景
使用场景:您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
使用场景总结:
- 要创建一系列复杂的对象,需要提供很多的创建信息;
- 想要将对象的创建和使用解藕,隐藏创建对象时候的“代码逻辑”;
- 应用创建对象的代码分布在多个不同的地方,而不是仅在一个函数/方法中,造成我们无法跟踪这些对象时;
优点:
- 一个调用者想创建一个对象,只要知道其名称就可以了,不需要知道其他详细信息。
- 作为调用者而言,屏蔽产品的具体实现,调用者只关心产品的接口。
- 工厂方法可以在必要时创建新的对象,从而提高性能和内存使用率
缺点:
当有新的类型要加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这违背了“开闭原则”。在简单工厂模式中,所有的产品都是由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。
应用案例:
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。例如,需要有一个方法集中负责连接不同的数据库(mysql,sqllite等)。
- 设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
3 实现步骤
工厂模式主要有三种实现方式:简单工厂,工厂方法,抽象工厂。
- 简单工厂模式:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
- 工厂方法模式:用来生产同一等级结构中的固定产品。(支持增加任意产品)
- 抽象工厂模式:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
3.1 简单工厂
通过一个函数,根据不同的输入参数,返回不同的实例对象。
在简单工厂模式中,一个工厂类处于对产品类进行实例化的中心位置上,它知道每一个产品类的细节,并决定何时哪一个产品类应当被实例化。简单工厂模式的优点是能够使客户端独立于产品的创建过程,并且在系统中引入新产品时无需对客户端进行修改,缺点是当有新产品要加入到系统中时,必须对工厂类进行修改,以加入必要的处理逻辑。简单工厂模式的致命弱点就是处于核心地位的工厂类,因为一旦它无法确定要对哪个类进行实例化时,就无法使用该模式,而工厂方法模式则可以很好地避免这一问题。
3.2 工厂模式方法
根据业务需求,通过各业务对应的工厂类实例化对象。在简单工厂的基础上更好的符合了开闭原则(新业务不应该侵入修改旧有的函数或方法)。
工厂方法模式是一种用来创建对象的多态方法(polymorphic method),它在抽象父类中声明用来创建对象的方法接口,而具体子类则通过覆盖该方法将对象的创建过程局部化,包括是否实例化一个子类,以及是否对它进行初始化等等。从某种程度上说,工厂方法可以看成是构造函数的特殊化,其特殊性表现在能够用一致的方法来创建不同的对象,而不用担心当前正