工厂模式是创建型设计模式的核心成员之一,它通过将对象的创建过程封装起来,实现了创建逻辑与使用逻辑的解耦,从而提升了代码的灵活性、可维护性和可扩展性。
简单工厂模式,又称静态工厂方法模式,它定义一个工厂类,该类包含一个静态或实例方法,根据传入的参数来创建并返回不同的具体产品对象。
以下示例展示了一个计算器程序,通过简单工厂模式创建不同的运算对象。
from abc import ABCMeta, abstractmethod
# 1. 抽象产品:运算类
class Operation(metaclass=ABCMeta):
def __init__(self, num1, num2):
self.num1 = num1
self.num2 = num2
@abstractmethod
def result(self):
pass
# 2. 具体产品:各种运算
class AddOp(Operation):
def result(self):
return self.num1 + self.num2
class SubOp(Operation):
def result(self):
return self.num1 - self.num2
class MulOp(Operation):
def result(self):
return self.num1 * self.num2
class DivOp(Operation):
def result(self):
return self.num1 / self.num2 if self.num2 != 0 else "Error"
# 3. 工厂类
class OperateFactory:
@staticmethod
def create_operate(operator, num1, num2):
if operator == '+':
return AddOp(num1, num2)
elif operator == '-':
return SubOp(num1, num2)
elif operator == '*':
return MulOp(num1, num2)
elif operator == '/':
return DivOp(num1, num2)
else:
raise ValueError("不支持的运算符")
# 客户端代码
if __name__ == "__main__":
num1 = float(input("输入第一个数字: "))
num2 = float(input("输入第二个数字: "))
op = input("输入运算符 (+, -, *, /): ")
operation = OperateFactory.create_operate(op, num1, num2)
print(f"结果: {operation.result()}")
优点:实现简单,有效隐藏了对象创建细节,客户端与具体产品类解耦。
缺点:工厂类职责过重,违反了单一职责原则;当需要新增产品(如增加乘方运算)时,必须修改工厂类的代码,这违反了开闭原则(对扩展开放,对修改关闭)。因此,它更适用于产品类型相对固定且不会频繁变化的场景。
为了克服简单工厂模式的缺点,工厂方法模式应运而生。它将对象的创建过程抽象化,定义一个创建对象的接口,但将具体的创建工作延迟到子类中去完成。这样,工厂父类就不知道也不需要知道具体要创建哪种产品。
以下示例展示了如何用工厂方法模式来创建不同的支付对象。
from abc import ABCMeta, abstractmethod
# 1. 抽象产品:支付接口
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# 2. 具体产品
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付 {money} 元")
class Alipay(Payment):
def __init__(self, use_huabei=False):
self.use_huabei = use_huabei
def pay(self, money):
if self.use_huabei:
print(f"支付宝花呗支付 {money} 元")
else:
print(f"支付宝余额支付 {money} 元")
# 3. 抽象工厂
class PaymentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
# 4. 具体工厂
class WechatPayFactory(PaymentFactory):
def create_payment(self):
return WechatPay()
class AlipayFactory(PaymentFactory):
def create_payment(self):
return Alipay()
class HuabeiPayFactory(PaymentFactory):
def create_payment(self):
return Alipay(use_huabei=True)
# 客户端代码
if __name__ == "__main__":
# 根据需要选择不同的工厂
factory = HuabeiPayFactory() # 可以轻松替换为 WechatPayFactory() 或 AlipayFactory()
payment = factory.create_payment()
payment.pay(100)
优点:完全遵循开闭原则。要增加新的产品(如ApplePay),只需新增对应的具体产品类和具体工厂类,无需修改任何现有代码。系统具有很好的扩展性。
缺点:随着产品种类的增加,系统中类的数量会成对增加(一个产品对应一个工厂),导致系统复杂度提升。
抽象工厂模式是工厂方法模式的进一步延伸,它用于创建一系列相关或相互依赖的对象家族,而无需指定它们具体的类。例如,要生产一部智能手机,需要配套的芯片、操作系统和外壳,这些部件是相互关联的。
以下示例展示了抽象工厂模式如何创建不同品牌的手机组件。
from abc import ABCMeta, abstractmethod
# ----- 抽象产品族 -----
class CPU(metaclass=ABCMeta):
@abstractmethod
def show(self):
pass
class OS(metaclass=ABCMeta):
@abstractmethod
def show(self):
pass
class Shell(metaclass=ABCMeta):
@abstractmethod
def show(self):
pass
# ----- 具体产品族:小米系列 -----
class SnapdragonCPU(CPU):
def show(self):
print("骁龙处理器")
class AndroidOS(OS):
def show(self):
print("安卓系统")
class CeramicShell(Shell):
def show(self):
print("陶瓷机身")
# ----- 具体产品族:苹果系列 -----
class AppleCPU(CPU):
def show(self):
print("A系列仿生芯片")
class IOS(OS):
def show(self):
print("iOS系统")
class GlassShell(Shell):
def show(self):
print("玻璃机身")
# ----- 抽象工厂 -----
class PhoneFactory(metaclass=ABCMeta):
@abstractmethod
def make_cpu(self):
pass
@abstractmethod
def make_os(self):
pass
@abstractmethod
def make_shell(self):
pass
# ----- 具体工厂 -----
class XiaomiFactory(PhoneFactory):
def make_cpu(self):
return SnapdragonCPU()
def make_os(self):
return AndroidOS()
def make_shell(self):
return CeramicShell()
class AppleFactory(PhoneFactory):
def make_cpu(self):
return AppleCPU()
def make_os(self):
return IOS()
def make_shell(self):
return GlassShell()
# ----- 客户端 -----
def assemble_phone(factory: PhoneFactory):
cpu = factory.make_cpu()
os = factory.make_os()
shell = factory.make_shell()
print("组装完成一部手机,配置如下:")
cpu.show()
os.show()
shell.show()
if __name__ == "__main__":
print("生产小米手机:")
assemble_phone(XiaomiFactory())
print("\n生产苹果手机:")
assemble_phone(AppleFactory())
优点:保证了产品族内对象的兼容性。客户端与具体产品的创建完全解耦,并且切换整个产品族(如从小米换到苹果)非常容易,只需更换具体工厂即可。
缺点:扩展产品族困难(增加一个新品牌容易),但扩展产品等级结构困难(如在手机中新增一个“电池”产品类型),因为需要修改所有工厂类的接口,这违反了开闭原则。
↶ 返回首页 ↶