上一章节介绍了简单工厂模式,简单工厂模式,适合子类品种不多,一般3个左右,而且有违设计模式的开放-封闭原则。而工厂模式正是对简单工厂模式的一种提升。工厂模式是一组简单工厂模式,同时在客户端决定所要生产产品的类别。以下列举了简单工厂模式和工厂模式的区别和联系。
模式 | 简单工厂模式 | 工厂模式 |
适合场景 | 一个工厂,一组产品 | 多个工厂,一系列产品 |
产品实例化 | 在工厂中进行逻辑判断,决定实例化哪种产品 | 在客户端,直接指定具体的工厂类 |
分配内存 | 在运行时,才会去实例化对象 | 在编译时,就会为对象分配空间 |
扩展性 | 需要更改工厂类中的逻辑判断方法,客户端无变化 | 原有工厂类不受影响,只需要增加新的产品和工厂 |
封闭性 | 破坏开放-封闭原则 | 遵循开放-封闭原则 |
以下用简单工厂模式里的计算器为例,用工厂模式来实现。将每个运算操作提升为一种工厂,每个工厂只有一种产品。
实例中计算器用工厂模式实现:
工厂模式的UML图:
#!/usr/bin/env python
import abc
import ast
class OperFactory:
__metaclass__=abc.ABCMeta
@abc.abstractmethod
def CreateOperation(self):
pass
class AddFactory(OperFactory):
def CreateOperation(self):
return OperationAdd()
class SubFactory(OperFactory):
def CreateOperation(self):
return OperationSub()
class MultiFactory(OperFactory):
def CreateOperation(self):
return OperationMul()
class DiviFactory(OperFactory):
def CreateOperation(self):
return OperationDiv()
class Operation:
def __init__(self):
self.__numberA=None
self.__numberB=None
@property
def numberA(self):
return self.__numberA
@numberA.setter
def numberA(self,value):
self.__numberA=value
@property
def numberB(self):
return self.__numberB
@numberB.setter
def numberB(self,value):
self.__numberB=value
@abc.abstractmethod
def GetResult(self):
pass
class OperationAdd(Operation):
def GetResult(self):
return self.numberA+self.numberB
class OperationSub(Operation):
def GetResult(self):
return self.numberA-self.numberB
class OperationMul(Operation):
def GetResult(self):
return self.numberA*self.numberB
class OperationDiv(Operation):
def GetResult(self):
if(numberB==0):
raise Exception ("除数不能为0")
return self.numberA/self.numberB
if __name__ == '__main__':
numA = ast.literal_eval(input("请输入数字A: "))
oper_sympol = input("请输入运算符(+,-,*,/): ")
operator = {'+':AddFactory(),'-':SubFactory(),'*':MultiFactory(),'/':DiviFactory()}
factory = operator.get(oper_sympol)
oper = factory.CreateOperation()
oper.numberA = numA
oper.numberB = ast.literal_eval(input("请输入数字B: "))
print(oper.GetResult())
工厂方法的好处就是定义了一个创建对象统一接口,让实例化对象延迟到子类。
《大话设计模式》中雷锋工厂的代码在我的GitHub中有,这里就不贴出来了。
GitHub地址为:https://github.com/givemefiveagain/Design_Pattern/commit/e5b3ebd5703dd26e464314a0d6b7d8251844fd35