前言
工厂模式属于构建型模式;
工厂模式,顾名思义就是我们可以通过一个指定的“工厂”获得需要的“产品”,在设计模式中主要用于抽象对象的创建过程,让用户可以指定自己想要的对象而不必关心对象的实例化过程,这样做的好处是:
- 用户只需通过固定的接口而不是直接去调用类的实例化方法来获得一个对象的实例
- 隐藏了实例创建过程的复杂度
- 解耦了生产实例和使用实例的代码
- 降低了维护的复杂性。
简单工厂
假设我们有两个“产品”分别是Mercedes和BMW的汽车,如果没有“工厂”来生产它们,我们就要在代码中自己进行实例化,如:
mercedes = Mercedes()
bmw = BMW()
但现实中,你可能会面对很多汽车产品,而且每个产品的构造参数还不一样,这样在创建实例时会遇到麻烦。
这时就可以构造一个“简单工厂”把所有汽车实例化的过程封装在里面。
#coding=utf-8 class Mercedes(object): """梅赛德斯 """ def __repr__(self): return "Mercedes-Benz" class BMW(object): """宝马 """ def __repr__(self): return "BMW" class SimpleCarFactory(object): """简单工厂 """ @staticmethod def product_car(name): if name == 'mb': return Mercedes() elif name == 'bmw': return BMW() c1 = SimpleCarFactory.product_car('mb') c2 = SimpleCarFactory.product_car('bmw')
工厂方法
工厂方法就通过抽象方法/接口的机制约束对象方法;
虽然有了1个简单的工厂,但在实际使用工厂的过程中,我们会发现新问题:如果我们要新增一个“产品”,例如Audi的汽车,我们除了新增一个Audi类外还要修改
SimpleCarFactory内的product_car方法。这样就违背了软件设计中的开闭原则[1],即在扩展新的类时,尽量不要修改原有代码。
所以我们在简单工厂的基础上把SimpleCarFactory抽象成不同的工厂,每个工厂对应生成自己的产品,这就是工厂方法。
#coding=utf-8 import abc class AbstractFactory(object): """抽象工厂 """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def product_car(self): pass class MercedesFactory(AbstractFactory): """梅赛德斯工厂 """ def product_car(self): return Mercedes() class BMWFactory(AbstractFactory): """宝马工厂 """ def product_car(self): return BMW() c1 = MercedesFactory().product_car() c2 = BMWFactory().product_car()
抽象工厂
工厂方法虽然解决了我们“修改代码”的问题,但如果我们要生产很多产品,就会发现我们同样需要写很多对应的工厂类。比如如果MercedesFactory和BMWFactory不仅生产小汽车,还要生产SUV,那我们用工厂方法就要再多构造两个生产SUV的工厂类。
所以为了解决这个问题,我们就要再更进一步的抽象工厂类,让一个工厂可以生产同一类的多个产品,这就是抽象工厂。
具体实现如下:
#coding=utf-8 import abc # 2种小汽车 class Mercedes_C63(object): """梅赛德斯 C63 """ def __repr__(self): return "Mercedes-Benz: C63" class BMW_M3(object): """宝马 M3 """ def __repr__(self): return "BMW: M3" # 2种SUV class Mercedes_G63(object): """梅赛德斯 G63 """ def __repr__(self): return "Mercedes-Benz: G63" class BMW_X5(object): """宝马 X5 """ def __repr__(self): return "BMW: X5" #抽象工厂类 class AbstractFactory(object): """抽象工厂 可以生产小汽车外,还可以生产SUV """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def product_car(self): pass @abc.abstractmethod def product_suv(self): pass class MercedesFactory(AbstractFactory): """梅赛德斯工厂 """ def product_car(self): return Mercedes_C63() def product_suv(self): return Mercedes_G63() class BMWFactory(AbstractFactory): """宝马工厂 """ def product_car(self): return BMW_M3() def product_suv(self): return BMW_X5() c1 = MercedesFactory().product_car() s1 = MercedesFactory().product_suv() print(c1, s1) s2 = BMWFactory().product_suv() c2 = BMWFactory().product_car() print(c2, s2)