【python 设计模式】工厂模式

2024-01-10 00:00:00

工厂模式是创建型设计模式的核心成员之一,它通过将对象的创建过程封装起来,实现了创建逻辑与使用逻辑的解耦,从而提升了代码的灵活性、可维护性和可扩展性。

简单工厂模式

简单工厂模式,又称静态工厂方法模式,它定义一个工厂类,该类包含一个静态或实例方法,根据传入的参数来创建并返回不同的具体产品对象。

以下示例展示了一个计算器程序,通过简单工厂模式创建不同的运算对象。

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())

优点:保证了产品族内对象的兼容性。客户端与具体产品的创建完全解耦,并且切换整个产品族(如从小米换到苹果)非常容易,只需更换具体工厂即可。

缺点:扩展产品族困难(增加一个新品牌容易),但扩展产品等级结构困难(如在手机中新增一个“电池”产品类型),因为需要修改所有工厂类的接口,这违反了开闭原则

返回首页

本文总阅读量  次
皖ICP备17026209号-3
总访问量: 
总访客量: