基于Python的设计模式之创建型模型
文章目录
- 设计模式概述
- 设计模式的基础
- 设计模式的六大原则
- 创建型模式
- 单例模式
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
- 创建型模式小结
设计模式概述
设计模式(GOF,即 Gang of Four,四人组提出的经典设计模式)是面向对象系统中对重要且重复出现的设计进行系统化总结的方案。它包含模式名称、问题、解决方法和效果这四个基本要素,有助于开发者更高效地设计和构建软件系统。
设计模式的基础
- 对象/类:面向对象编程的三大特性——封装、继承和多态是设计模式的基石。封装将数据和操作封装在一起,继承允许子类继承父类的属性和方法,多态则使得不同的对象可以对同一消息做出不同的响应。
- 接口:接口是一种特殊的类,规定了继承它的类必须实现的方法。在 Python 中,有两种常见的实现方式:
- 使用
NotImplementedError
:通过在基类方法中抛出NotImplementedError
异常,强制子类实现该方法。 - 使用
abc
模块:利用ABCMeta
元类和@abstractmethod
装饰器,明确声明抽象方法,使类成为抽象基类。
- 使用
设计模式的六大原则
- 开闭原则:软件实体应该对扩展开放,对修改关闭。这意味着在不修改现有代码的情况下,能够通过扩展来添加新的功能。
- 里氏替换原则:所有引用基类的方法必须能够透明地使用其子类的对象。即子类可以替换父类,而不会影响程序的正确性。
- 依赖倒置原则:高层模块不应依赖低层模块,二者都应依赖于抽象。通过依赖抽象,可以降低模块之间的耦合度。
- 接口隔离原则:使用多个专门的接口,而不是单一的总接口。这样可以避免类实现不必要的方法,提高代码的内聚性。
- 迪米特法则:软件实体应尽可能少地与其他实体发生相互作用,以降低耦合度。
- 单一职责原则:一个类应该只有一个导致其变更的原因。每个类应该只负责一项职责,提高代码的可维护性。
创建型模式
单例模式
- 定义:确保一个类只有一个实例,并提供一个全局访问点。
- 适用场景:当类只能有一个实例,并且需要全局访问时,如配置管理类、日志记录器等。
- 优点:对唯一实例的受控访问,避免命名空间污染。
- 示例代码:
class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if cls._instance is None:cls._instance = super().__new__(cls)return cls._instance# 测试单例模式
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2) # 输出: True
简单工厂模式
- 定义:通过一个工厂类负责创建产品类的实例,而不直接向客户端暴露对象创建的实现细节。
- 优点:隐藏了对象创建的实现细节,客户端无需修改代码。
- 缺点:违反单一职责原则,添加新产品时需修改工厂类代码。
- 示例代码:
from abc import abstractmethod, ABCMetaclass Payment(metaclass=ABCMeta):@abstractmethoddef pay(self, money):passclass Alipay(Payment):def pay(self, money):print(f'支付宝支付 {money} 元')class PaymentFactory:def create_payment(self, method):if method == 'alipay':return Alipay()else:raise ValueError(f'未知支付方式: {method}')factory = PaymentFactory()
payment = factory.create_payment('alipay')
payment.pay(100)
工厂方法模式
- 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个产品类。
- 适用场景:需要生产多种复杂对象时,降低耦合度。
- 示例代码:
from abc import abstractmethod, ABCMetaclass Payment(metaclass=ABCMeta):@abstractmethoddef pay(self, money):passclass Alipay(Payment):def pay(self, money):print(f'支付宝支付 {money} 元')class PaymentFactory(metaclass=ABCMeta):@abstractmethoddef create_payment(self):passclass AlipayFactory(PaymentFactory):def create_payment(self):return Alipay()factory = AlipayFactory()
payment = factory.create_payment()
payment.pay(100)
抽象工厂模式
- 定义:定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。
- 适用场景:系统要独立于产品创建与组合时。
- 示例代码:
from abc import abstractmethod, ABCMetaclass PhoneShell(metaclass=ABCMeta):@abstractmethoddef get_shell_info(self):passclass MiPhoneShell(PhoneShell):def get_shell_info(self):return '小米手机壳'class PhoneFactory(metaclass=ABCMeta):@abstractmethoddef make_shell(self):passclass MiFactory(PhoneFactory):def make_shell(self):return MiPhoneShell()factory = MiFactory()
shell = factory.make_shell()
print(shell.get_shell_info())
建造者模式
- 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 适用场景:当创建复杂对象的算法应独立于该对象的组成部分时。
- 示例代码:
class Player:def __init__(self, face=None, body=None):self.face = faceself.body = bodydef __str__(self):return f'Player with {self.face} face and {self.body} body'class PlayerBuilder:def build_face(self):passdef build_body(self):passdef get_player(self):passclass BeautifulWomanBuilder(PlayerBuilder):def build_face(self):return '漂亮脸蛋'def build_body(self):return '苗条身材'def get_player(self):face = self.build_face()body = self.build_body()return Player(face, body)builder = BeautifulWomanBuilder()
player = builder.get_player()
print(player)
原型模式
- 定义:通过复制现有对象来创建新对象,而不是通过实例化类。
- 适用场景:当创建对象的成本较高,或者需要创建多个相似对象时。
- 示例代码:
import copyclass Prototype:def clone(self):return copy.deepcopy(self)class ConcretePrototype(Prototype):def __init__(self, value):self.value = valuedef __str__(self):return str(self.value)# 创建原型对象
prototype = ConcretePrototype(10)# 克隆对象
clone = prototype.clone()print(prototype) # 输出: 10
print(clone) # 输出: 10
创建型模式小结
使用抽象工厂、原型或建造者模式的设计通常比工厂方法模式更灵活,但也更复杂。设计者通常从工厂方法开始,随着需求的变化,逐步演化到其他创建模式。了解多种模式可以为设计提供更多选择,根据具体的应用场景选择合适的设计模式,能够提高软件的可维护性、可扩展性和可复用性。