【Python笔记-设计模式】建造者模式

news2024/12/23 17:54:01

一、说明

又称生成器,是一种创建型设计模式,使其能够分步骤创建复杂对象。允许使用相同的创建代码生成不同类型和形式的对象。

(一) 解决问题

  1. 对象的创建问题:当一个对象的构建过程复杂,且部分构建过程相互独立时,可以使用建造者模式。例如,一个软件系统中需要创建一个复杂的对象,这个对象由多个部分组成,而这些部分可以独立地进行变更,这时候就可以使用建造者模式。
  2. 解耦问题:建造者模式将一个复杂对象的构建函数进行分离,使得同样的构建过程可以创建不同的表示。用户只需要指定需要建造的类型,不需要知道建造的过程和细节。

(二) 使用场景

  • 结构复杂:当对象有非常复杂的内部结构,有许多属性时
  • 拆分大量参数的构造函数
  • 希望使用代码创建不同形式的产品,制造过程相似且仅有细节上的差异

二、结构

  1. 生成器 (Builder)接口声明在所有类型生成器中通用的产品构造步骤。
  2. 具体生成器 (Concrete Builders)提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品。
  3. 产品 (Products)是最终生成的对象。由不同生成器构造的产品无需属于同一类层次结构或接口。
  4. 主管 (Director)类定义调用构造步骤的顺序,这样你就可以创建和复用特定的产品配置。
  5. 客户端 (Client)必须将某个生成器对象与主管类关联。一般情况下,你只需通过主管类构造函数的参数进行一次性关联即可。此后主管类就能使用生成器对象完成后续所有的构造任务。但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。在这种情况下,你在使用主管类生产产品时每次都可以使用不同的生成器。

三、伪代码

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
__doc__ = """
建造者模式

例:复用相同的对象构造代码来生成不同类型的产品——例如汽车 (Car)——及其相应的使用手册 (Manual)。
"""


class Car:
    """产品类"""

    def __init__(self):
        self.brand = None
        self.seats = None
        self.engine = None
        self.trip_computer = None
        self.gps = None

    def __str__(self):
        return "汽车概况:\n     " + f"{self.__dict__}"


class Manual:
    """使用手册类"""

    def __init__(self):
        self.sections = []

    def add_section(self, feature, description):
        self.sections.append((feature, description))

    def __str__(self):
        return "使用手册:\n     " + "\n     ".join(
            f"{feature} - {description}" for feature, description in self.sections
        )


class CarBuilder:
    """生成器类"""

    def __init__(self):
        self._manual = None
        self._car = None
        self.reset()

    def reset(self):
        self._car = Car()
        self._manual = Manual()

    def set_brand(self, brand):
        self._car.brand = brand
        self._manual.add_section("Brand", f"这辆车的品牌是 {brand}")
        return self

    def set_seats(self, seats):
        self._car.seats = seats
        self._manual.add_section("Seats", f"这辆车有 {seats} 个座位")
        return self

    def set_engine(self, engine):
        self._car.engine = engine
        self._manual.add_section("Engine", f"这辆车配备了一个 {engine} 引擎")
        return self

    def set_trip_computer(self, trip_computer):
        self._car.trip_computer = trip_computer
        if trip_computer:
            self._manual.add_section("Trip Computer", "这辆汽车装有行车电脑。")
        return self

    def set_gps(self, gps):
        self._car.gps = gps
        if gps:
            self._manual.add_section("GPS", "这辆汽车装有全球定位系统(GPS)。")
        return self

    def get_car(self):
        return self._car

    def get_manual(self):
        return self._manual


class Director:
    """
    主管类
    主管只负责按照特定顺序执行生成步骤。由于客户端可以直接控制生成器,所以严格意义上来说,主管类并不是必需的。
    """

    @staticmethod
    def construct_sports_car1(builder):
        builder.reset()
        builder.set_brand("宝马").set_seats(4).set_engine("SportEngine").set_trip_computer(True).set_gps(True)

    @staticmethod
    def construct_sports_car2(builder):
        builder.reset()
        builder.set_brand("奔驰").set_seats(6)


def client_code():
    """客户端代码"""
    director = Director()

    # 构建汽车和使用手册
    car_builder = CarBuilder()
    director.construct_sports_car1(car_builder)
    print(car_builder.get_car())
    print(car_builder.get_manual())
    print()
    director.construct_sports_car2(car_builder)
    print(car_builder.get_car())
    print(car_builder.get_manual())


if __name__ == "__main__":
    """
    汽车概况:
         {'brand': '宝马', 'seats': 4, 'engine': 'SportEngine', 'trip_computer': True, 'gps': True}
    使用手册:
         Brand - 这辆车的品牌是 宝马
         Seats - 这辆车有 4 个座位
         Engine - 这辆车配备了一个 SportEngine 引擎
         Trip Computer - 这辆汽车装有行车电脑。
         GPS - 这辆汽车装有全球定位系统(GPS)。
    
    汽车概况:
         {'brand': '奔驰', 'seats': 6, 'engine': None, 'trip_computer': None, 'gps': None}
    使用手册:
         Brand - 这辆车的品牌是 奔驰
         Seats - 这辆车有 6 个座位
    """
    client_code()

四、优缺点

优点

  • 你可以分步创建对象,暂缓创建步骤或递归运行创建步骤。
  • 生成不同形式的产品时,你可以复用相同的制造代码。
  • 单一职责原则。你可以将复杂构造代码从产品的业务逻辑中分离出来。

缺点

  • 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1419211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea 创建 spring boot

1.创建步骤 2. 编码添加 2.1 这是自动生成的启动函数 package com.example.comxjctest4;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication public class Application {publi…

STM32控制DHT11温湿度传感器模块获取温湿度数据

时间记录:2024/1/29 一、DHT11引脚介绍 (1)VCC:电源引脚,3.3-5.5V (2)DATA:数据输入输出引脚 (3)NC:保留引脚,悬空即可 (…

postgresql慢查询排查和复现

postgresql慢查询排查和复现 一. 介绍一张表:pg_stat_activity pg_stat_activity 是 PostgreSQL 中一个非常有用的系统视图,提供了有关当前数据库连接和活动查询的信息。通过查询这个视图,你可以获取有关正在执行的查询、连接的用户、进程 …

VitePress-04-文档中的表情符号的使用

说明 vitepress 的文档中是支持使用表情符号的,像 😂 等常用的表情都是支持的。 本文就来介绍它的使用方式。 使用语法 语法 : :表情名称: 例如 : :joy: 😂 使用案例代码 # 体会【表情】的基本使用 > hello world …

设计模式——2_0 职责链(Chain of Responsibility)

楼下一个男人并得要死,那家隔壁的一家唱着留声机,对面是弄孩子。楼上有两人狂笑;还有打牌声,河中的船上有女人哭她死去的母亲。人类的悲欢并不相通,我只觉得他们吵闹 ——鲁迅 定义 使多个对象都有机会处理请求&#…

VScode注释快捷键,RStudio注释快捷键, Texmaker注释快捷键

VScode:一款界面简单的代码编辑器;RStudio: R语言的IDE,包含代码编辑器,运行,绘图窗口等;Texmaker:Latex编译器(编辑编译),界面简单,个人认为比Te…

sqli-labs第一关

1.判断是否存在注入,注入是字符型还是数字型? ?id1 and 11 ?id1 and 12 因为输入and 11与and 12 回显正常,所以该地方不是数字型。 ?id1 ?id1-- 输入单引号后报错,在单引号后添加--恢复正常,说明存在字符注入 2.猜解SQL查…

安全 输入输出类 XSS CSRF

输入输出类(留言板) 执行JS语句(XSS漏洞) XSS漏洞(有输入框就可能-见框就X) 反射型 语句植入并执行 存储型 语句植入到数据库,调用数据库就执行 UA头判断访问者浏览器信息 可以XSS php…

亚组分析、P交互、P趋势是什么?如何计算呢?

亚组分析、P交互、P趋势是什么?如何计算呢? (1)亚组分析如何计算? (2)P交互作用的计算方法? (3)P趋势如何计算? (1)亚组…

SNP干货分享:SAP数据脱敏的具体实施步骤

随着信息技术的飞速发展,大数据时代的到来使得数据成为国家经济、企业竞争力和个人隐私的重要载体。在这种背景下,数据安全问题日益凸显,各国政府纷纷出台相关法规以保护数据安全。我国也不断完善数据安全法规体系,以确保国家利益…

十分钟发布自己的NFT

概述 本文将以一个例子来说明如何在opensea快速发布自己的NFT智能合约(ERC721)。本着DRY(Dont Repeat Yourself)原则,我们需要站在巨人的肩膀上来搭建自己的应用,使用经过社区审计和实践检验的代码可以有效…

python统计分析——样本方差的分布

参考资料:用python动手学统计学 1、导入库 import numpy as np import pandas as pd import scipy as sp from scipy import statsfrom matplotlib import pyplot as plt import seaborn as sns 2、数据准备 建立一个平均数为4,标准差为0.8的正态分布…

腾讯云4核16G服务器价格,用于幻兽帕鲁Palworld专用

腾讯云幻兽帕鲁服务器4核16G、8核32G和16核64G配置可选,4核16G14M带宽66元一个月、277元3个月,8核32G22M配置115元1个月、345元3个月,16核64G35M配置580元年1个月、1740元3个月、6960元一年,腾讯云百科txybk.com分享腾讯云幻兽帕鲁…

自然语言处理 TF-IDF

✅作者简介:人工智能专业本科在读,喜欢计算机与编程,写博客记录自己的学习历程。 🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心&…

Java强训day10(选择题编程题)

选择题 public class Test01 {public static void main(String[] args) {try{int i 100 / 0;System.out.print(i);}catch(Exception e){System.out.print(1);throw new RuntimeException();}finally{System.out.print(2);}System.out.print(3);} }编程题 题目1 import jav…

重构改善既有代码的设计-学习(六):处理继承关系

1、函数上移(Pull Up Method) 无论何时,只要系统内出现重复,你就会面临“修改其中一个却未能修改另一个”的风险。通常,找出重复也有一定的难度。 所以,某个函数在各个子类中的函数体都相同(它们…

leetcode hot100跳跃游戏Ⅱ

本题和上一题还是有不一样的地方,这个题中,我们需要记录我们跳跃的步数并尽可能的满足最小的跳跃步数到达终点。 那么我们还是采用覆盖范围的概念,但是我们需要两个,一个是在当前位置的覆盖范围,另一个是下一步的覆盖…

Linux的 .bashrc 有什么作用?

一、.bashrc 是什么? 有什么用? .bashrc是一个存储在你的home目录下的隐藏文件,它用来配置和自定义你的终端环境和行为。 每次你启动一个新的终端时,.bashrc文件就会被执行,加载你设置的环境变量,别名,函数…

深度学习-自注意力机制

文字编码 one-hot编码,让模型自己去学习怎么进行编码 常见的输出 1.每个词都有一个输出值 2.每个句子输出一个值,情感分类 3.输入与输出长度不对应,翻译任务,生成任务。 RNN最早的语言处理 RNN解决的是模型去考虑前面的输入…

数字图像处理(实践篇)二十八 使用OpenCV Python中的K-means对图像进行颜色量化处理

目录 1 颜色量化 2 实践 在某些时候,不可避免的某些设备只能生成有限数量的颜色。因此需要执行颜色量化。选择使用cv2.kmeans()函数对颜色量化应用k-means聚类。 1 颜色量化 使用K-means聚类在图像中实现颜色量化的步骤如下: ① 导入依赖库