当前位置:   article > 正文

Python 设计模式(创建型)

Python 设计模式(创建型)

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种将一组相关或相互依赖的对象集合起来创建的方式,而无需指定它们的具体类。抽象工厂模式可以被看作是工厂方法模式的延伸,它不仅创建单一对象,而是创建一系列相关对象的家族。

  1. 抽象工厂(Abstract Factory):定义了创建一系列相关对象的方法接口。通常是一个接口或者抽象类。

  2. 具体工厂(Concrete Factory):实现抽象工厂接口,负责创建一组具体对象。

  3. 抽象产品(Abstract Product):定义了一组相关产品的接口。通常是一个接口或者抽象类。

  4. 具体产品(Concrete Product):实现了抽象产品接口,是抽象工厂所创建的具体对象。

场景

  1. 需要创建一组相关或相互依赖的对象:如果系统中有一组相关的对象需要同时创建,并且它们之间存在一定的依赖关系,可以考虑使用抽象工厂模式。这样可以确保创建的对象之间的配合和一致性。

  2. 系统中有多个产品族:如果系统中有多个产品族,且每个产品族的产品有一定的关联性,可以使用抽象工厂模式来管理这些产品族。这样可以使得产品族之间的变化和扩展更加容易。

  3. 需要独立于具体工厂的创建过程:如果系统需要独立于具体工厂的创建过程,而只关心产品的组合和表示,可以考虑使用抽象工厂模式。这样可以使得系统更加灵活,可以方便地切换不同的产品组合。

  4. GUI 库:一个图形用户界面(GUI)库需要创建不同风格的按钮、文本框和下拉框等组件,可以使用抽象工厂模式来管理不同风格组件的创建。

  5. 操作系统平台:一个操作系统平台需要支持不同的文件系统和网络协议,可以使用抽象工厂模式来管理不同平台下文件系统和网络协议的创建。

  6. 数据库访问:一个数据库访问库需要支持不同数据库(如 MySQL、PostgreSQL 等)的访问,可以使用抽象工厂模式来管理不同数据库访问类的创建。

示例

# 抽象产品 - 按钮
class Button:
    def click(self):
        pass

# 具体产品 - Windows 风格按钮
class WindowsButton(Button):
    def click(self):
        print("Windows 风格按钮被点击")

# 具体产品 - Mac 风格按钮
class MacButton(Button):
    def click(self):
        print("Mac 风格按钮被点击")

# 抽象产品 - 文本框
class TextBox:
    def input_text(self):
        pass

# 具体产品 - Windows 风格文本框
class WindowsTextBox(TextBox):
    def input_text(self):
        print("在 Windows 风格文本框中输入文本")

# 具体产品 - Mac 风格文本框
class MacTextBox(TextBox):
    def input_text(self):
        print("在 Mac 风格文本框中输入文本")

# 抽象工厂
class GUIFactory:
    def create_button(self):
        pass

    def create_textbox(self):
        pass

# 具体工厂 - Windows 风格工厂
class WindowsGUIFactory(GUIFactory):
    def create_button(self):
        return WindowsButton()

    def create_textbox(self):
        return WindowsTextBox()

# 具体工厂 - Mac 风格工厂
class MacGUIFactory(GUIFactory):
    def create_button(self):
        return MacButton()

    def create_textbox(self):
        return MacTextBox()

# 客户端代码
def create_gui(factory):
    button = factory.create_button()
    textbox = factory.create_textbox()
    return button, textbox

def main():
    windows_gui = create_gui(WindowsGUIFactory())
    mac_gui = create_gui(MacGUIFactory())

    # 测试
    windows_button, windows_textbox = windows_gui
    windows_button.click()          # 输出: Windows 风格按钮被点击
    windows_textbox.input_text()    # 输出: 在 Windows 风格文本框中输入文本

    mac_button, mac_textbox = mac_gui
    mac_button.click()              # 输出: Mac 风格按钮被点击
    mac_textbox.input_text()        # 输出: 在 Mac 风格文本框中输入文本

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 输出结果
Windows 风格按钮被点击
在 Windows 风格文本框中输入文本
Mac 风格按钮被点击
在 Mac 风格文本框中输入文本
  • 1
  • 2
  • 3
  • 4

单例模式

单例模式是一种创建型设计模式,它确保类只有一个实例,并提供一个全局访问点。

  1. 只有一个实例:单例模式确保一个类只有一个实例对象。

  2. 全局访问点:单例模式提供一个全局访问点,使得程序可以访问该实例。

场景

  1. 资源共享:当希望多个对象共享同一资源时,可以使用单例模式。例如,数据库连接池就是一个常见的单例模式的应用场景。

  2. 控制对象的数量:当希望限制类的实例化次数时,可以使用单例模式。例如,线程池就可以使用单例模式来控制线程的数量。

  3. 全局对象:当希望在整个系统中使用一个全局对象时,可以使用单例模式。例如,日志记录器、配置管理器等都可以使用单例模式来实现。

实现方式

  1. 懒汉式:在第一次调用时创建实例对象。
class Singleton:
    _instance = None

    def __init__(self):
        if Singleton._instance is not None:
            raise ValueError("An instance of this class already exists")
        Singleton._instance = self

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

# 客户端代码
def main():
    # 创建两个实例,但它们实际上是同一个对象
    singleton1 = Singleton.get_instance()
    singleton2 = Singleton.get_instance()

    # 打印输出,可以看到两个实例具有相同的内存地址
    print(singleton1 is singleton2)  # 输出: True

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  1. 饿汉式:在类加载时就创建实例对象。
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

# 客户端代码
def main():
    # 创建两个实例,但它们实际上是同一个对象
    singleton1 = Singleton()
    singleton2 = Singleton()

    # 打印输出,可以看到两个实例具有相同的内存地址
    print(singleton1 is singleton2)  # 输出: True

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. 线程安全的单例模式:确保在多线程环境下仍然能够正常工作。
import threading

class Singleton:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super().__new__(cls)
        return cls._instance

# 客户端代码
def main():
    # 创建两个实例,但它们实际上是同一个对象
    singleton1 = Singleton()
    singleton2 = Singleton()

    # 打印输出,可以看到两个实例具有相同的内存地址
    print(singleton1 is singleton2)  # 输出: True

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  1. 基于模块:使用 Python 模块系统的特性实现单例模式。
  • singleton_module.py
class Singleton:
    value = None

def get_singleton():
    if Singleton.value is None:
        Singleton.value = Singleton()
    return Singleton.value
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • client.py
import singleton_module

# 客户端代码
def main():
    # 创建两个实例,但它们实际上是同一个对象
    singleton1 = singleton_module.get_singleton()
    singleton2 = singleton_module.get_singleton()

    # 打印输出,可以看到两个实例具有相同的内存地址
    print(singleton1 is singleton2)  # 输出: True

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

工厂方法模式

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个用于创建对象的接口,但将实际创建工作推迟到子类中。这样,工厂方法模式允许一个类在不改变其结构的情况下,改变它所实例化的具体类。

  1. 抽象产品(Abstract Product):定义了产品的接口,是工厂方法所创建对象的基类。

  2. 具体产品(Concrete Product):实现了抽象产品接口的具体对象。

  3. 抽象工厂(Abstract Factory):定义了创建产品的工厂方法的接口。

  4. 具体工厂(Concrete Factory):实现了抽象工厂接口的具体工厂类,负责创建具体产品对象。

场景

  1. 创建对象的具体类不是事先知道的:当一个类需要创建对象的具体类不是在编写代码时就能确定的,而是在运行时动态确定时,可以使用工厂方法模式。

  2. 避免直接依赖于具体类:工厂方法模式可以让客户端代码通过接口调用工厂方法来创建对象,而不需要直接依赖于具体类,从而降低了耦合度。

  3. 需要创建一组相关的对象:如果系统需要创建一组相关的对象,但具体的对象类型由子类决定,可以使用工厂方法模式来管理对象的创建。

  4. 需要扩展系统功能:工厂方法模式符合开闭原则,可以方便地扩展系统功能。当需要添加新的具体产品类时,只需要添加新的具体工厂类即可,不需要修改已有代码。

  5. 图形界面库:比如在 GUI 库中,根据不同的操作系统(如 Windows、MacOS、Linux)需要创建不同的按钮、文本框等组件对象。

  6. 数据库访问类库:在数据库访问类库中,根据不同的数据库(如 MySQL、PostgreSQL、SQLite)需要创建不同的连接对象。

  7. 日志记录器:在日志记录器中,根据不同的日志输出目标(如控制台、文件、数据库)需要创建不同的日志记录器对象。

示例

from abc import ABC, abstractmethod

# 抽象产品 - 车
class Car(ABC):
    @abstractmethod
    def drive(self):
        pass

# 具体产品 - Toyota 车
class ToyotaCar(Car):
    def drive(self):
        print("驾驶 Toyota 车")

# 具体产品 - Tesla 车
class TeslaCar(Car):
    def drive(self):
        print("驾驶 Tesla 车")

# 抽象工厂
class CarFactory(ABC):
    @abstractmethod
    def create_car(self):
        pass

# 具体工厂 - Toyota 工厂
class ToyotaFactory(CarFactory):
    def create_car(self):
        return ToyotaCar()

# 具体工厂 - Tesla 工厂
class TeslaFactory(CarFactory):
    def create_car(self):
        return TeslaCar()

# 客户端代码
def drive_car(factory):
    car = factory.create_car()
    car.drive()

def main():
    toyota_factory = ToyotaFactory()
    tesla_factory = TeslaFactory()

    drive_car(toyota_factory)  # 输出: 驾驶 Toyota 车
    drive_car(tesla_factory)   # 输出: 驾驶 Tesla 车

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 输出结果
驾驶 Toyota 车
驾驶 Tesla 车
  • 1
  • 2

简单工厂模式

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,它提供了一种将对象的创建过程封装起来的方式。在简单工厂模式中,有一个工厂类负责根据客户端的需求创建相应的对象,而客户端无需知道具体的创建逻辑。

  1. 产品(Product):被创建的对象的基类或接口,它定义了产品的通用行为。
  2. 具体产品(Concrete Product):实现产品接口的具体对象。
  3. 工厂类(Factory):负责创建具体产品的类。客户端通过调用工厂类的方法来创建产品,而不直接实例化具体产品类。

场景

  1. 对象的创建逻辑相对简单:如果对象的创建逻辑比较简单,并且不太可能变化,可以考虑使用简单工厂模式。这样可以将对象的创建过程封装起来,使客户端代码更加简洁。

  2. 需要对客户端隐藏对象的创建细节:简单工厂模式可以隐藏对象的创建细节,客户端只需要知道如何向工厂类提供参数,而不需要了解对象是如何创建的。

  3. 需要根据不同的条件创建不同类型的对象:如果需要根据不同的条件来创建不同类型的对象,可以使用简单工厂模式。例如,根据用户输入的不同命令创建不同类型的工具对象。

  4. 对象的数量较少且稳定:如果需要创建的对象数量较少,并且这些对象的种类相对稳定,不太容易变化,可以考虑使用简单工厂模式。

示例

class Car:
    def __init__(self, brand):
        self.brand = brand

class CarFactory:
    def create_car(self, brand):
        if brand == "Toyota":
            return Car("Toyota")
        elif brand == "Tesla":
            return Car("Tesla")
        else:
            raise ValueError("未知车辆品牌")

def main():
    # 创建车辆工厂
    car_factory = CarFactory()
    
    # 制造丰田车和特斯拉车
    toyota_car = car_factory.create_car("Toyota")
    tesla_car = car_factory.create_car("Tesla")

    # 打印输出结果
    print("丰田车品牌:", toyota_car.brand)  # 输出: Toyota
    print("特斯拉车品牌:", tesla_car.brand)    # 输出: Tesla

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 输出结果
丰田车品牌: Toyota
特斯拉车品牌: Tesla
  • 1
  • 2

建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

  1. 产品(Product):表示被构建的复杂对象。产品类通常包含多个部件,不同的建造者可以构建不同的产品对象。

  2. 抽象建造者(Builder):定义了构建产品对象的抽象接口,包括创建各个部件的方法。

  3. 具体建造者(Concrete Builder):实现了抽象建造者接口,负责构建产品对象的各个部件,并将这些部件组装成最终的产品对象。

  4. 指挥者(Director):负责使用建造者对象构建产品对象的方法。指挥者通常包含一个构建方法,该方法接收一个建造者对象作为参数,然后根据具体的构建过程调用建造者的方法来构建产品对象。

场景

  1. 创建复杂对象:当一个对象包含多个部分,且构建过程比较复杂时,可以使用建造者模式。通过将构建过程分解成多个步骤,并由不同的建造者负责构建不同的部分,可以简化对象的构建过程。

  2. 对象的构建过程需要灵活性:当需要灵活地控制对象的构建过程,并且可以根据不同需求创建不同的表示时,可以使用建造者模式。通过定义不同的具体建造者,可以创建不同表示的产品对象。

  3. 创建对象的过程需要复用:当需要复用相同的构建过程来创建不同的对象时,可以使用建造者模式。通过复用相同的构建过程,可以提高代码的复用性和可维护性。

  4. 创建复杂的文档对象:例如,一个文档对象可能包含标题、正文、图像、表格等多个部分,不同类型的文档可能具有不同的部件组成,可以使用建造者模式来构建不同类型的文档对象。

  5. 创建复杂的菜单对象:例如,一个菜单对象可能包含多个菜品、饮料、甜点等多个部分,可以使用建造者模式来构建不同类型的菜单对象,如午餐菜单、晚餐菜单、酒水菜单等。

示例

# 产品 - 电脑
class Computer:
    def __init__(self):
        self.case = None
        self.cpu = None
        self.memory = None
        self.hard_drive = None
        self.graphics_card = None

    def __str__(self):
        info = (f"电脑配置:\n"
                f"机箱:{self.case}\n"
                f"CPU:{self.cpu}\n"
                f"内存:{self.memory}\n"
                f"硬盘:{self.hard_drive}\n"
                f"显卡:{self.graphics_card}")
        return info

# 抽象建造者
class ComputerBuilder:
    def __init__(self):
        self.computer = Computer()

    def build_case(self):
        pass

    def build_cpu(self):
        pass

    def build_memory(self):
        pass

    def build_hard_drive(self):
        pass

    def build_graphics_card(self):
        pass

# 具体建造者 - 游戏电脑
class GamingComputerBuilder(ComputerBuilder):
    def build_case(self):
        self.computer.case = "大型塔式机箱"

    def build_cpu(self):
        self.computer.cpu = "i9-9900K"

    def build_memory(self):
        self.computer.memory = "32GB DDR4"

    def build_hard_drive(self):
        self.computer.hard_drive = "1TB SSD + 2TB HDD"

    def build_graphics_card(self):
        self.computer.graphics_card = "RTX 3080"

# 指挥者
class Director:
    def __init__(self, builder):
        self.builder = builder

    def construct_computer(self):
        self.builder.build_case()
        self.builder.build_cpu()
        self.builder.build_memory()
        self.builder.build_hard_drive()
        self.builder.build_graphics_card()

    def get_computer(self):
        return self.builder.computer

# 客户端代码
def main():
    gaming_builder = GamingComputerBuilder()
    director = Director(gaming_builder)
    director.construct_computer()
    gaming_computer = director.get_computer()
    print(gaming_computer)

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 输出结果
电脑配置:
机箱:大型塔式机箱
CPU:i9-9900K
内存:32GB DDR4
硬盘:1TB SSD + 2TB HDD
显卡:RTX 3080
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

原型模式

原型模式(Prototype Pattern)是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化新对象。在原型模式中,一个原型对象充当了新对象的模板,新对象通过复制原型对象来初始化,并可以根据需要进行修改。

  1. 简化对象创建:原型模式通过复制现有对象来创建新对象,避免了使用构造函数和初始化参数的复杂性。

  2. 提高性能:与直接实例化对象相比,通过复制现有对象创建新对象通常更快。

  3. 允许动态配置对象:新对象可以根据需要对原型对象进行修改,以满足不同的需求。

场景

  1. 对象的创建成本高:当对象的创建成本较高,或者对象的创建过程比较复杂时,可以使用原型模式。通过复制现有对象来创建新对象,可以节省创建对象的时间和资源成本。

  2. 需要创建多个相似对象:当需要创建多个相似但不完全相同的对象时,可以使用原型模式。原型模式允许在现有对象的基础上进行修改和定制,从而快速创建多个相似对象。

  3. 避免构造函数的复杂性:当对象的构造函数包含复杂的初始化逻辑或参数时,可以使用原型模式来避免构造函数的复杂性。通过复制现有对象来创建新对象,可以避免使用构造函数和初始化参数。

  4. 需要动态配置对象:当需要根据不同的需求动态配置对象时,可以使用原型模式。原型模式允许在创建新对象时根据需要对现有对象进行修改和定制,从而满足不同的需求。

  5. 缓存对象:原型模式可以用于缓存已创建的对象,避免重复创建相同的对象,提高性能和效率。

  6. 深拷贝对象:原型模式可以用于执行深拷贝操作,创建一个与现有对象相同但不同实例的对象。

  7. 创建测试数据:原型模式可以用于创建测试数据,快速创建多个相似但不完全相同的对象用于测试。

示例

import copy

class Prototype:
    def __init__(self):
        self._objects = {}

    def register_object(self, name, obj):
        self._objects[name] = obj

    def unregister_object(self, name):
        del self._objects[name]

    def clone(self, name, **attrs):
        obj = copy.deepcopy(self._objects.get(name))
        obj.__dict__.update(attrs)
        return obj

class Car:
    def __init__(self):
        self.make = "Toyota"
        self.model = "Camry"
        self.year = 2020

    def __str__(self):
        return f"{self.year} {self.make} {self.model}"

# 客户端代码
def main():
    prototype = Prototype()

    # 注册原型对象
    car = Car()
    prototype.register_object("car", car)

    # 克隆对象并修改属性
    cloned_car = prototype.clone("car", year=2021)
    print(cloned_car)  # 输出: 2021 Toyota Camry

if __name__ == "__main__":
    main()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 输出结果
2021 Toyota Camry
  • 1
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号