设计模式Python版 建造者模式

文章目录


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、建造者模式

建造者模式(Builder Pattern)

  • 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  • 解决问题:如何一步步创建一个包含多个组成部分的复杂对象?

  • 使用场景:

    • 建造者模式向客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品
    • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  • 组成:

    • 复杂产品(Product):最终要构建的复杂对象。 复杂对象是指那些包含多个成员变量的对象,这些成员变量也称为部件或零件。

    • 抽象建造者(Builder):为一个抽象接口,定义了构建产品的各个部件的操作。

    • 具体建造者(Concrete Builder):实现抽象建造者的接口,定义并明确各个部件的具体实现。

    • (可省略)指挥者(Director):负责安排已有模块的构建顺序,它主要用来控制产品的创建过程。

  • 优点:

    • 客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需的建造者类型即可。
    • 建造者模式关注如何一步一步地创建一个复杂对象,不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,增加新的建造者非常方便,无须修改已有代码,系统具有较好的扩展性。
    • 可以更加精细地控制产品的创建过程。
  • 缺点:

    • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似。否则不适用。

二、建造者模式示例

使用建造者模式来实现游戏角色的创建

  • ActorController充当指挥者,ActorBuilder充当抽象建造者,HeroBuilder、AngelBuilder和DevilBuilder充当具体建造者,Actor充当复杂产品。
python 复制代码
"""复杂产品"""

class Actor:
    def __init__(self, type=None, sex=None, face=None, costume=None, hairstyle=None):
        self.type = type
        self.sex = sex
        self.face = face
        self.costume = costume
        self.hairstyle = hairstyle


"""抽象建造者"""

class ActorBuilder:
    def __init__(self):
        self.actor = Actor()

    def build_type(self):
        raise NotImplementedError

    def build_sex(self):
        raise NotImplementedError

    def build_face(self):
        raise NotImplementedError

    def build_costume(self):
        raise NotImplementedError

    def build_hairstyle(self):
        raise NotImplementedError

    def create_actor(self) -> Actor:
        return self.actor


"""具体建造者"""

class HeroBuilder(ActorBuilder):
    def build_type(self):
        self.actor.type = "英雄"

    def build_sex(self):
        self.actor.sex = "男"

    def build_face(self):
        self.actor.face = "英俊"

    def build_costume(self):
        self.actor.costume = "盔甲"

    def build_hairstyle(self):
        self.actor.hairstyle = "飘逸"


class AngelBuilder(ActorBuilder):
    def build_type(self):
        self.actor.type = "天使"

    def build_sex(self):
        self.actor.sex = "女"

    def build_face(self):
        self.actor.face = "漂亮"

    def build_costume(self):
        self.actor.costume = "白裙"

    def build_hairstyle(self):
        self.actor.hairstyle = "披肩长发"


"""指挥者"""

class ActorController:
    def construct(self, ab: ActorBuilder):
        ab.build_type()
        ab.build_sex()
        ab.build_face()
        ab.build_costume()
        ab.build_hairstyle()
        return ab.create_actor()

引入配置文件config.json

json 复制代码
{
    "class_name": "AngelBuilder"
}

读取配置文件的工具类JsonUtil

python 复制代码
# 模块 utils.py
from pathlib import Path
import json


class JsonUtil:
    @staticmethod
    def get_class_name():
        """读取配置文件,返回配置文件中的配置"""
        path = Path("config.json")
        contents = path.read_text(encoding="utf-8")
        conf = json.loads(contents)
        return conf.get("class_name", None)

客户端代码

python 复制代码
import actors
from actors import Actor, ActorBuilder, ActorController
from utils import JsonUtil


def display(actor: Actor):
    print(f"类型:{actor.type}")
    print(f"性别:{actor.sex}")
    print(f"面容:{actor.face}")
    print(f"服装:{actor.costume}")
    print(f"发型:{actor.hairstyle}")


class_name = JsonUtil.get_value("class_name")
klass = getattr(actors, class_name, None)
if klass:
    ab: ActorBuilder = klass()  # 反射生成具体建造者对象
    ac = ActorController()
    actor = ac.construct(ab)  # 通过指挥者创建完整的建造者对象
    display(actor)

输出结果

sh 复制代码
类型:天使
性别:女      
面容:漂亮    
服装:白裙    
发型:披肩长发

三、省略指挥者(建议)

当construct()方法较为简单时,建议省略指挥者。简化了系统结构,但加重了抽象建造者类的职责。

  • 将construct()方法直接放在抽象建造者中,具体建造者可以沿用或改写construct()方法。
python 复制代码
"""复杂产品(不变)"""


"""抽象建造者(用construct()方法替换原来的create_actor()方法)"""

class ActorBuilder:
    def __init__(self):
        self.actor = Actor()

    def build_type(self):
        raise NotImplementedError

    def build_sex(self):
        raise NotImplementedError

    def build_face(self):
        raise NotImplementedError

    def build_costume(self):
        raise NotImplementedError

    def build_hairstyle(self):
        raise NotImplementedError

    def construct(self) -> Actor:
        self.build_type()
        self.build_sex()
        self.build_face()
        self.build_costume()
        self.build_hairstyle()
        return self.actor
    
    
"""具体建造者(不变)"""


"""指挥者(可以删除)"""

客户端代码

python 复制代码
import actors
from actors import Actor, ActorBuilder
from utils import JsonUtil


def display(actor: Actor):
    print(f"类型:{actor.type}")
    print(f"性别:{actor.sex}")
    print(f"面容:{actor.face}")
    print(f"服装:{actor.costume}")
    print(f"发型:{actor.hairstyle}")


class_name = JsonUtil.get_value("class_name")
klass = getattr(actors, class_name, None)
if klass:
    ab: ActorBuilder = klass()  # 反射生成具体建造者对象
    actor = ab.construct()
    display(actor)

四、钩子方法的引入

钩子方法的返回类型通常为boolean类型,方法名一般为isxx()

  • 钩子方法定义在抽象建造者类中,提供默认的实现,对应的具体建造者可以覆盖钩子方法。例如:
python 复制代码
"""抽象建造者"""
class ActorBuilder:
    #...
    
    def is_bareheaded(self):
        return False
    
    #...
  • construct()方法的作用是:实现更加精细地控制产品的创建过程
  • 通过在construct()方法中,配合使用钩子方法,实现更灵活的建造过程。
python 复制代码
"""抽象建造者"""
class ActorBuilder:
	#...
    
    def construct(self) -> Actor:
        self.build_type()
        self.build_sex()
        self.build_face()
        self.build_costume()
        if not self.is_bareheaded():
            self.build_hairstyle()
        return self.actor
    
    #...

您正在阅读的是《设计模式Python版》专栏!关注不迷路~

相关推荐
Draina1 小时前
CBC填充预言攻击-CBC Padding Oracle Crypto Attack
python·安全·web安全·网络安全·密码学·安全性测试
Angel Q.2 小时前
特征提取 | DINO 到 DINOv3
图像处理·python
不如语冰2 小时前
AI大模型入门-pytorch-张量2 tensor创建
python
NPE~2 小时前
[AI]Agent开发——ADK框架使用
人工智能·python·ai·教程·adk·agent开发
矮个史蒂芬2 小时前
统计verilog .v文件中output 的bit数
python
gwf2163 小时前
磨损均衡算法(Wear Leveling)——SSD如何让每块闪存“公平退休“?
运维·数据库·人工智能·python·嵌入式硬件·算法·智能硬件
爱吃提升3 小时前
python 分布式爬虫、爬虫合规与综合实战项目
分布式·爬虫·python
审小匠OpenCPAi3 小时前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
元Y亨H4 小时前
Pandas 解析 Excel 导致的内存溢出(MemoryError)
python·excel
金銀銅鐵5 小时前
[Python] 用 turtle 来绘制瑞典国旗
python