首页 > 其他分享 >设计模式之生成器模式

设计模式之生成器模式

时间:2024-12-04 09:04:21浏览次数:13  
标签:std ComputerBuilder string 对象 生成器 模式 设计模式

目录

1.简介

2.结构

3.使用场景

4.实例

5.优缺点

6.与其他模式的关系

7.总结


1.简介

        生成器模式(Builder Pattern)是一种创建型设计模式,它允许你通过一步一步构建复杂对象,而不是通过一个包含大量参数的构造函数或方法。该模式特别适用于需要生成的对象具有多个可选属性,且这些属性的组合会导致大量构造函数重载的情况。

        生成器模式通过将对象的构建过程分解成多个步骤,使得每一步都可以单独配置。这样不仅提高了代码的可读性和可维护性,还使得构建过程更加灵活和可扩展。

        与其他创建型模式不同的是,生成器模式允许你在一个过程中创建一个对象,而无需等待所有部分都准备好。这种模式特别适用于需要构造不同表示或状态的复杂对象时。

2.结构

        生成器模式的UML结构图如下所示:

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

3.使用场景

1)使用生成器模式可避免“重叠构造函数(telescopicconstructor)”的出现。

        假设你的构造函数中有十个可选参数,那么调用该函数会非常不方便;因此,你需要重载这个构造函数,新建几个只有较少参数的简化版。但这些构造函数仍需调用主构造函数,传递一些默认数值来替代省略掉的参数。生成器模式让你可以分步骤生成对象,而且允许你仅使用必须的步骤。应用该模式后,你再也不需要将几十个参数塞进构造函数里了。

2)当你希望使用代码创建不同形式的产品(例如石头或木头房屋)时,可使用生成器模式。

        如果你需要创建的各种形式的产品,它们的制造过程相似且仅有细节上的差异,此时可使用生成器模式。基本生成器接口中定义了所有可能的制造步骤,具体生成器将实现这些步骤来制造特定形式的产品。同时,主管类将负责管理制造步骤的顺序。

3)使用生成器构造组合树或其他复杂对象

        当一个对象的构建过程非常复杂,涉及多个步骤和多个部件时,使用生成器模式可以将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

        例如,构建一个汽车对象可能涉及设置车身、引擎、车轮和内饰等多个部件,每个部件都有多种选择。使用生成器模式,可以逐步构建汽车对象,并根据需要选择不同的部件。

4.实例

下面我将展示一个稍微复杂一些的应用场景,即构建一个包含多个可选组件的计算机配置对象。

首先,我们定义一个Computer类,它代表我们要构建的计算机对象:

#include <iostream>
#include <string>
#include <vector>
#include <memory>

class Computer {
private:
    std::string caseType;
    std::string cpu;
    std::string gpu;
    std::string ram;
    std::string storage;
    std::vector<std::string> peripherals;

    // 禁止直接实例化
    Computer(const std::string& caseType, const std::string& cpu, const std::string& gpu,
             const std::string& ram, const std::string& storage,
             const std::vector<std::string>& peripherals)
        : caseType(caseType), cpu(cpu), gpu(gpu), ram(ram), storage(storage), peripherals(peripherals) {}

    friend class ComputerBuilder;

public:
    void display() const {
        std::cout << "Case Type: " << caseType << "\n";
        std::cout << "CPU: " << cpu << "\n";
        std::cout << "GPU: " << gpu << "\n";
        std::cout << "RAM: " << ram << "\n";
        std::cout << "Storage: " << storage << "\n";
        std::cout << "Peripherals: ";
        for (const auto& peripheral : peripherals) {
            std::cout << peripheral << " ";
        }
        std::cout << "\n";
    }
};

接下来,我们定义一个ComputerBuilder类,用于逐步构建Computer对象:

class ComputerBuilder {
protected:
    std::string caseType;
    std::string cpu;
    std::string gpu;
    std::string ram;
    std::string storage;
    std::vector<std::string> peripherals;

public:
    virtual ~ComputerBuilder() = default;

    ComputerBuilder& setCaseType(const std::string& caseType) {
        this->caseType = caseType;
        return *this;
    }

    ComputerBuilder& setCpu(const std::string& cpu) {
        this->cpu = cpu;
        return *this;
    }

    ComputerBuilder& setGpu(const std::string& gpu) {
        this->gpu = gpu;
        return *this;
    }

    ComputerBuilder& setRam(const std::string& ram) {
        this->ram = ram;
        return *this;
    }

    ComputerBuilder& setStorage(const std::string& storage) {
        this->storage = storage;
        return *this;
    }

    ComputerBuilder& addPeripheral(const std::string& peripheral) {
        peripherals.push_back(peripheral);
        return *this;
    }

    virtual Computer build() const = 0;
};

注意,这里我们将ComputerBuilder定义为一个抽象类,并声明了一个纯虚函数build,这样我们就可以有不同的具体实现来构建不同类型的计算机。

现在,我们定义一个具体的GamingComputerBuilder类来构建游戏计算机:

class GamingComputerBuilder : public ComputerBuilder {
public:
    GamingComputerBuilder() {
        // 可以设置一些默认配置
        setCaseType("ATX Mid Tower");
        setCpu("Intel i9");
        // ... 其他默认配置
    }

    Computer build() const override {
        return Computer(caseType, cpu, gpu, ram, storage, peripherals);
    }
};

GamingComputerBuilder中,我们可以设置一些默认配置,或者覆盖父类的方法来提供特定的配置选项。

最后,我们定义一个ComputerDirector类(可选)来管理构建过程,并展示如何使用这些类来构建一个计算机对象:

class ComputerDirector {
private:
    ComputerBuilder* builder;

public:
    ComputerDirector(ComputerBuilder* builder) : builder(builder) {}

    void setBuilder(ComputerBuilder* builder) {
        this->builder = builder;
    }

    Computer constructGamingComputer() {
        builder->setGpu("NVIDIA RTX 3090");
        builder->setRam("32GB DDR4");
        builder->setStorage("2TB SSD");
        builder->addPeripheral("Gaming Keyboard");
        builder->addPeripheral("Gaming Mouse");
        // ... 其他配置
        return builder->build();
    }
};

int main() {
    GamingComputerBuilder gamingBuilder;
    ComputerDirector director(&gamingBuilder);

    // 或者使用自定义的构建步骤
    // gamingBuilder.setCaseType("Custom Case");
    // ... 其他设置
    // Computer customComputer = gamingBuilder.build();

    Computer gamingComputer = director.constructGamingComputer();
    gamingComputer.display();

    return 0;
}

在这个例子中,我们展示了如何使用生成器模式来构建一个包含多个可选组件的计算机配置对象。通过定义抽象的ComputerBuilder类和具体的GamingComputerBuilder类,我们可以灵活地构建不同类型的计算机,并且可以通过ComputerDirector类来管理构建过程(尽管在这个例子中ComputerDirector是可选的,但在更复杂的场景中它可能会很有用)。

5.优缺点

优点:

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

缺点:

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

6.与其他模式的关系

与工厂模式的关系

  • 工厂模式:主要用于生产各种对象,这些对象通常是兄弟类,继承自同一个基类。兄弟子类通过实现基类接口,展现不同的行为,并由工厂函数创建。然而,工厂模式在创建对象时并不关注构造细节,因此在处理复杂对象的生成时可能会显得力不从心。
  • 生成器模式:同样用于对象的生成,但更侧重于构造细节,增加了额外的构建流程,以便处理复杂对象的构建需求。生成器模式将对象构造的代码从产品类中抽取出来,放在一个名为生成器的独立对象中,并允许通过不同的生成器来创建不同形式的对象。
  • 对比:相较于工厂模式,生成器模式提供了更灵活和详细的对象构造方式。当对象相对简单时,可以使用工厂模式;而当对象复杂且需要详细配置时,生成器模式则更为适用。

与抽象工厂模式的关系

  • 抽象工厂模式:专注于生成一系列相关对象,但它在对象构造复杂时,其能力也有限。抽象工厂模式通过定义一个接口,使得客户端可以创建相关或依赖对象的家族,而无需明确指定具体类。
  • 生成器模式:虽然也用于创建对象,但更侧重于对象的逐步构造和细节配置。生成器模式允许开发者通过不同的生成器来创建具有不同配置和形式的对象。
  • 联系与区别:两者都提供了对象的创建方式,但抽象工厂模式更侧重于对象的家族创建,而生成器模式则更侧重于对象的逐步构造和细节配置。此外,抽象工厂模式通常会立即返回产品,而生成器模式则允许在获取产品前执行一些额外的构造步骤。

与其他模式的关系

  • 桥接模式:生成器模式可以与桥接模式结合使用,其中主管类负责抽象工作,而各种不同的生成器负责实现工作。这种结合可以使得对象构造更加灵活和可扩展。
  • 原型模式:原型模式通过复制现有对象来创建新对象,而生成器模式则通过逐步构造来创建对象。虽然两者在对象创建方式上有所不同,但在某些情况下,它们可以相互补充,共同实现复杂的对象创建需求。
  • 单例模式:抽象工厂、生成器和原型模式都可以用单例来实现,以确保对象的唯一性和全局可访问性。然而,这种实现方式并不常见,因为它可能会增加系统的复杂性和维护成本。

7.总结

        生成器模式通过将复杂对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。它允许逐步构建对象,通过调用生成器对象的方法来添加或修改对象的部件。

标签:std,ComputerBuilder,string,对象,生成器,模式,设计模式
From: https://blog.csdn.net/haokan123456789/article/details/144206279

相关文章

  • ovs和交换机端口模式
    ovs端口模式tag对应vlanid,取值范围是0-4095。#设置端口vlan模式(默认是access,还有trunk等)ovs-vsctlsetporttap0vlan_mode=access#设置端口tagovs-vsctlsetporttap0tag=101#清除配置ovs-vsctlclearporttap0[vlan_mode|tag]模式作用access经......
  • RabbitMQ 双机 镜像集群模式
    目录准备工作组建集群rabbitmq01rabbitmq02设置HA策略注意补充命令行检验登录管理界面检验准备工作#/etc/hosts172.16.0.11rabbitmq01172.16.0.12rabbitmq02组建集群rabbitmq01rabbitmq-server-detachedrabbitmqctlstatus#复制cookiecp~/.erlang.cookierabbitmq......
  • 设计模式浅说
    通过翻一些源码,以及在项目里看到一些不太有强业务关联的内容使用了不少设计模式,当然也有一些内容为了设计模式而丢失了可读性,导致旁人看代码时很难理清当时什么情况什么场景什么原因什么需求什么业务逻辑等。所以在此简要铺开一下设计模式,先知道有什么,看到时知道怎么回事,遇到问题......
  • Sigrity Power DC Single-BoardPackage ET Co-Simulation模式进行单板电热协同仿真分
    SigrityPowerDCSingle-BoardPackageETCo-Simulation模式进行单板电热协同仿真分析操作指导SigrityPowerDCSingle-BoardPackageIRDropAnalysis模式进行单板压降仿真分析操作指导详细介绍了单板的压降仿真分析流程,下面同样以这个例子进行电热协同仿真分析具体操作......
  • Sigrity Power DC Single-BoardPackage IR Drop Analysis模式进行封装基板压降仿真分
    SigrityPowerDCSingle-BoardPackageIRDropAnalysis模式进行封装基板压降仿真分析操作指导SigrityPowerDCSingle-BoardPackageIRDropAnalysis模式不仅可以用于PCB压降仿真分析,同样也可以用于封装基板的压降仿真分析,以下图为例进行说明具体操作如下双击打开Powe......
  • vxe-table 列宽拖拽模式设置,自适应列宽,固定列宽
    在使用vxe-table是,常用的列宽拖拽调整功能,通过列宽调整可以让用户灵活的自定义列宽。两种拖拽调整列宽模式分别用于不同场景。动态列宽分配模式调整列宽之后,对于未设置列宽的列会重新动态分配剩余宽度<template><div><vxe-gridv-bind="gridOptions"></vxe-grid>......
  • 聊聊如何利用kafka实现请求-响应模式
    前言在大多数场景中,我们经常使用kafka来做发布-订阅,在发布-订阅模型中,消息一旦发送就不再追踪后续处理,但在某些业务场景下,我们希望在发送消息后等待一个响应,然后根据这个响应来做我们后续的操作。在这种请求-响应模式,我们就可以利用springkafka的ReplyingKafkaTemplate来实现Re......
  • 社区团购中 2+1 链动模式商城小程序的创新融合与发展策略研究
    摘要:本文聚焦于社区团购这一新兴零售模式的发展态势,深入探讨2+1链动模式商城小程序与之融合的创新机制与应用策略。通过剖析社区团购的运营模式、优势特点以及发展现状,结合2+1链动模式商城小程序的功能特性,研究二者协同作用下在用户获取、留存、商业运营效率提升等方面的价......
  • 基于“微店 Park”模式下 2+1 链动模式商城小程序的创新发展与应用研究
    摘要:本文以“微店Park”从“开店工具”向“众创平台”的转型为背景,深入探讨2+1链动模式商城小程序在该平台情境下的应用潜力与创新发展路径。通过剖析“微店Park”的运营模式,包括灵活承租、低成本入驻、多元流量引流等特点,结合2+1链动模式商城小程序的功能机制,研究其在促......
  • 软件设计:实验 23:策略模式
    实验23:策略模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解策略模式的动机,掌握该模式的结构;2、能够利用策略模式解决实际问题。 [实验任务一]:旅行方式的选择旅游的出行方式有乘坐飞机旅行、乘火车旅行和自行车游,不同的旅游方式有不同的实现过程,客户可......