什么是工厂模式
工厂模式又称多态工厂模式和虚拟构造器模式,通过已经定义的工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
大白话解释
您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
代码实现
从上面说明来看可能还是不太清楚,下面我们用代码来一步一步的展现工厂模式。我们以写一个简单版的计算的代码来开始(只提供加减乘除的功能)
一般新手都会按照如下的方式进行开发
class Calculator(object):
def operate(self, sn1, sn2, operate_type):
"""
+-*/操作
:param sn1: 数字1
:param sn2: 数字2
:param operate_type: 操作类型
:return:
"""
if not isinstance(sn1, int) or not not isinstance(sn1, float):
raise Exception("sn1输入有误")
if not isinstance(sn2, int) or not not isinstance(sn2, float):
raise Exception("sn2输入有误")
if operate_type == '+':
return sn1 + sn2
elif operate_type == '-':
return sn1 - sn2
elif operate_type == '*':
return sn1 * sn2
elif operate_type == '/':
if sn2 != 0:
return sn1 / sn2
else:
raise Exception("除数不能等于0")
else:
return "暂不支持此功能"
print(Calculator().operate(1, 2, "+"))
这种写法,将加减乘除运算全放在一个Calculator类中实现。虽然实现了计算器的功能,但增加其他功能的话就必须在operate方法中进行修改。这样的代码不易于我们后期的维护,扩展以及复用,并且耦合性高。
接下来我们就使用简单工厂模式来实现下上面的功能
class CalculatorFactory(object):
def __init__(self, sn1, sn2):
if not isinstance(sn1, int) or not not isinstance(sn1, float):
raise Exception("sn1输入有误")
if not isinstance(sn2, int) or not not isinstance(sn2, float):
raise Exception("sn2输入有误")
self.sn1 = sn1
self.sn2 = sn2
def calculation_result(self):
pass
class Add(CalculatorFactory):
"""
加法
"""
def calculation_result(self):
return self.sn1 + self.sn2
class Sub(CalculatorFactory):
"""
减法
"""
def calculation_result(self):
return self.sn1 - self.sn2
class Mul(CalculatorFactory):
"""
乘法
"""
def calculation_result(self):
return self.sn1 * self.sn2
class Division(CalculatorFactory):
"""
除法
"""
def calculation_result(self):
if self.sn2 == 0:
raise Exception("除数不能为0")
return self.sn1 / self.sn2
class CreateCalculator(object):
def calculator_operate(self, sn1, sn2, operate_type):
if operate_type == '+':
return Add(sn1, sn2)
elif operate_type == '-':
return Sub(sn1, sn2)
elif operate_type == '*':
return Mul(sn1, sn2)
elif operate_type == '/':
return Division(sn1, sn2)
else:
# 扩展类
pass
简单工厂模式就是一个工厂对象根据不同参数创建不同的实例。工厂中包含了必要的逻辑,不需要考虑怎么实现。虽然相对于上一个版本已经有了一部分的优化,工厂模式的雏形已经显现出来,但是这个还是有一定的问题:工厂一旦需要生产新产品就需要修改工厂类的方法逻辑,违背了开放—封闭 原则(一个软件实体应当对扩展开放(open),则修改关闭(不修改原来的代码这就是closed))
接下来我们看下工厂模式
class CalculatorFactory(object):
"""
抽象工厂类
"""
def create_calculator(self):
pass
class CalculatorAdd(CalculatorFactory):
"""
具体工厂
"""
def create_calculator(self):
return Add()
class OperateProduct(object):
"""
抽象产品类(+ - * / 等等)
"""
def get_result(self, sn1, sn2):
pass
class Add(OperateProduct):
"""
具体产品
"""
def get_result(self, sn1, sn2):
return sn1 + sn2
从上面可以看出工厂模式的四要素:
- 抽象产品类(Product):提供抽象方法供具体产品类实现
- 具体产品类(ConcreteProduct):提供具体的产品
- 抽象工厂类(Factory):提供抽象方法供具体工厂实现
- 具体工厂类(ConcreteFactory):提供具体的工厂
我们一般也是这样使用的:
- 创建抽象工厂类,定义具体工厂的公共接口;
- 创建抽象产品类 ,定义具体产品的公共接口;
- 创建具体产品类(继承抽象产品类) ,定义生产的具体产品;
- 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
- 外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
虽然我们通过工厂模式方便我们扩展以及复用,降低耦合性。但是看例子就可以看出来类太多了,所以一般如果要创建一系列复杂的对象,需要提供很多的创建信息;或者是我想要隐藏创建对象时候的“代码逻辑”,就需要使用工厂模式