当前位置: 首页 > article >正文

设计模式Python版 建造者模式

文章目录

  • 前言
  • 一、建造者模式
  • 二、建造者模式示例
  • 三、省略指挥者(建议)
  • 四、钩子方法的引入


前言

GOF设计模式分三大类:

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

一、建造者模式

建造者模式(Builder Pattern)

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

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

  • 使用场景:

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

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

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

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

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

  • 优点:

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

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

在这里插入图片描述

二、建造者模式示例

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

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

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

{
    "class_name": "AngelBuilder"
}

读取配置文件的工具类JsonUtil

# 模块 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)

客户端代码

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)

输出结果

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

三、省略指挥者(建议)

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

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


"""抽象建造者(用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
    
    
"""具体建造者(不变)"""


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

客户端代码

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

  • 钩子方法定义在抽象建造者类中,提供默认的实现,对应的具体建造者可以覆盖钩子方法。例如:
"""抽象建造者"""
class ActorBuilder:
    #...
    
    def is_bareheaded(self):
        return False
    
    #...

  • construct()方法的作用是:实现更加精细地控制产品的创建过程
  • 通过在construct()方法中,配合使用钩子方法,实现更灵活的建造过程。
"""抽象建造者"""
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版》专栏!关注不迷路~


http://www.kler.cn/a/526367.html

相关文章:

  • 阿里巴巴Qwen团队发布AI模型,可操控PC和手机
  • RDK X5运行DeepSeek-R1-Distill-Qwen-1.5B,体验长思维链的语言大模型!
  • 【视频+图文详解】HTML基础3-html常用标签
  • 回顾:Maven的环境搭建
  • 【张雪峰高考志愿填报】合集
  • pytorch逻辑回归实现垃圾邮件检测
  • 登录管理——认证方案(JWT、拦截器、ThreadLocal、短信验证)
  • 数据采集丨豆瓣电影详细数据的采集与可视化分析(scrapy+mysql+matplotlib+flask)
  • 遗传算法【Genetic Algorithm(GA)】求解函数最大值(MATLAB and Python实现)
  • 零碎的知识点(十二):卷积神经网络CNN通道数的理解!
  • 光伏设计新利器:绿虫仿真设计软件的优势
  • 【教学类-89-04】20250130新年篇04——九叠篆印章(九叠篆站+Python下载图片+Python组合文字)幼儿名字印章
  • CAPL学习资源推荐
  • 7层还是4层?网络模型又为什么要分层?
  • 乐理笔记——DAY02
  • 【深度分析】微软全球裁员计划不影响印度地区,将继续增加当地就业机会
  • 【浏览器 - Mac实时调试iOS手机浏览器页面】
  • AI DeepSeek-R1 Windos 10 环境搭建
  • 数据库简介-01
  • JavaScript 进阶(下)
  • 全国31省空间权重矩阵(地理相邻空间、公路铁路地理距离空间、经济空间)权重矩阵数据-社科数据
  • 【ComfyUI专栏】如何使用Git命令行安装非Manager收录节点
  • 下载一个项目到跑通的大致过程是什么?
  • Win10安装MySQL、Pycharm连接MySQL,Pycharm中运行Django
  • 内容检索(2025.01.30)
  • SAP SD学习笔记27 - 请求计划(开票计划)之1 - 定期请求