C++设计模式课件(11) - builder 生成器 | 构建器 模式



  • 参考课程:《C++设计模式》-李建忠
    李建忠-C++设计模式

1.动机 (Motivation)

➢在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
➢如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?

2.模式定义

将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。
          ——《设计模式:可复用面向对象软件的基础》

3.结构(Structure)

在这里插入图片描述

4.要点总结

在这里插入图片描述

Builder 模式的优点

➢将一个复杂对象的创建过程封装起来。
➢允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)。
➢向客户隐藏产品内部的表现。
➢产品的实现可以被替换,因为客户只看到一个抽象的接口。

Builder 模式的用途和缺点

➢经常被用来创建组合结构。
➢与工厂模式相比,采用Builder模式创建对象的客户,需要具备更多的领域知识。

要点:

➢Builder模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
➢变化点在哪里,封装哪里—— Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。
➢在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#) 。

5.《Head First 设计模式》实例的C++实现

在这里插入图片描述

场景

“模式乐园”是在对象村外围的一一个新 主题公园,他们请你为“模式乐园”制定一套度假计划。客人可以选择旅馆以及各种门票、餐厅订位,甚至也可以选择登记参加特殊的活动。想要制定–套度假计划,你需要建立像下面这样的结构:
在这里插入图片描述

你需要一个有弹性的设计

每个客人的度假计划可能都不太一样,例如天数、活动类型。比方说,当地居民可能不需要旅馆,但是想要用餐并参与特殊活动。而其他的客人可能是从外地飞过来的,所以需要旅馆、用餐和门票。
所以,你需要一个有弹性的数据结构,代表客人的规划,以及所有的变化:你也需要遵照一系列潜在的复杂顺序,创建这样的规划。你要如何才能够提供一种方式来创建这个复杂的结构,而不会和创建它的步骤混在一起呢?

为何使用生成器模式?

还记得迭代器吗?我们将迭代的过程封装进人一个独立的对象中,并向客户隐藏集合的内部表现。这里也是采取相同的想法:我们将旅游规划的创建过程,封装到一个对象中(让我们称此对象为生成器),然后让客户调用生成器为它创建旅游规划。
在这里插入图片描述

代码
旅游计划 类:
//Vacation.h
//假期类

#ifndef BUILDER_VACATION_H
#define BUILDER_VACATION_H

#include <string>

class Vacation {
public:
    Vacation() = default;
    ~Vacation() = default;

    [[nodiscard]] int getDay() const;
    void setDay(int day);

    [[nodiscard]] const std::string &getHotel() const;
    void setHotel(const std::string &hotel);

    [[nodiscard]] const std::string &getTickets() const;
    void setTickets(const std::string &tickets);

    [[nodiscard]] const std::string &getSpecialEvent() const;
    void setSpecialEvent(const std::string &specialEvent);

private:
    int day{};    //天数
    std::string hotel;  //旅馆
    std::string tickets;    //门票
    std::string specialEvent;   //特殊活动
};

#endif //BUILDER_VACATION_H
//vacation.cpp

#include "Vacation.h"

int Vacation::getDay() const {
    return day;
}

void Vacation::setDay(int day) {
    Vacation::day = day;
}

const std::string &Vacation::getHotel() const {
    return hotel;
}

void Vacation::setHotel(const std::string &hotel) {
    Vacation::hotel = hotel;
}

const std::string &Vacation::getTickets() const {
    return tickets;
}

void Vacation::setTickets(const std::string &mtickets) {
    Vacation::tickets = mtickets;
}

const std::string &Vacation::getSpecialEvent() const {
    return specialEvent;
}

void Vacation::setSpecialEvent(const std::string &mspecialEvent) {
    Vacation::specialEvent = mspecialEvent;
}
首先是抽象的生成-接口抽象的生成器类,定义一个创建产品过程的接口:
//AbstarctBuilder.h
//抽象的生成器 类

#ifndef BUILDER_ABSTARCTBUILDER_H
#define BUILDER_ABSTARCTBUILDER_H

#include <string>
#include <memory>
#include "Vacation.h"

class AbstarctBuilder {
public:
    AbstarctBuilder() = default;
    ~AbstarctBuilder() = default;
    virtual void buildDay(int day) = 0;
    virtual void addHotel(std::string hotel) = 0;
    virtual void addTickets(std::string tickets) = 0;
    virtual void addSpecialEvent(std::string specialEvent) = 0;
    virtual std::shared_ptr<Vacation> getVacationPlanner() = 0;
};

#endif //BUILDER_ABSTARCTBUILDER_H
然后是该接口的实现-具体的生成器类,这里是旅游计划创建过程的实现:
//VacationBuilder.h
//具体的生成器

#ifndef BUILDER_VACATIONBUILDER_H
#define BUILDER_VACATIONBUILDER_H


#include "AbstarctBuilder.h"

class VacationBuilder : public AbstarctBuilder{
public:
    VacationBuilder();
    ~VacationBuilder() = default;

    void buildDay(int day) override;
    void addHotel(std::string hotel) override;
    void addTickets(std::string tickets) override;
    void addSpecialEvent(std::string specialEvent) override;
    std::shared_ptr<Vacation> getVacationPlanner() override;

private:
    std::shared_ptr<Vacation> vacation;
};

#endif //BUILDER_VACATIONBUILDER_H
//VacationBuilder.cpp

#include "VacationBuilder.h"

VacationBuilder::VacationBuilder() {
    vacation = std::make_shared<Vacation>();
}

void VacationBuilder::buildDay(int day) {
    vacation->setDay(day);
}

void VacationBuilder::addHotel(std::string hotel) {
    vacation->setHotel(hotel);
}

void VacationBuilder::addTickets(std::string tickets) {
    vacation->setTickets(tickets);
}

void VacationBuilder::addSpecialEvent(std::string specialEvent) {
    vacation->setSpecialEvent(specialEvent);
}

std::shared_ptr<Vacation> VacationBuilder::getVacationPlanner() {
    return this->vacation;
}
接着是Client类,这里是构造一个使用builder对象的类,并通过内部方法封装AbstarctBuilder对象的方法:
//Client.h
//客户端类

#ifndef BUILDER_CLIENT_H
#define BUILDER_CLIENT_H

#include <utility>

#include "AbstarctBuilder.h"

class Client {
public:
    static std::shared_ptr<Vacation> constructPlanner(int day, std::string hotel, std::string tickets,
            std::string specialEvent, const std::shared_ptr<AbstarctBuilder>& builder){
        builder->buildDay(day);
        builder->addHotel(std::move(hotel));
        builder->addTickets(std::move(tickets));
        builder->addSpecialEvent(std::move(specialEvent));
        return builder->getVacationPlanner();
    }
};

#endif //BUILDER_CLIENT_H
测试:
//main.cpp
#include <iostream>
#include "VacationBuilder.h"
#include "Client.h"

using namespace std;

static void showPlanner(std::shared_ptr<Vacation> vacation)
{
    if(vacation->getDay() != 0 )
        cout << "假期天数为:" << vacation->getDay() << " 天。" << endl;
    if(!vacation->getHotel().empty())
        cout << "酒店定在:" << vacation->getHotel() << " 。" << endl;
    if(!vacation->getTickets().empty())
        cout << "买的门票是:" << vacation->getTickets() << " 。" << endl;
    if(!vacation->getSpecialEvent().empty())
        cout << "特殊活动是:" << vacation->getSpecialEvent() << " 。" << endl;
}

int main() {
    std::shared_ptr<AbstarctBuilder> builder = make_shared<VacationBuilder>();

    cout << "您好,这里是旅游服务,我们会根据您的需求为您打造完美的旅游计划!" << endl;

    cout << "第一位游客的安排:" << endl;
    std::shared_ptr<Client> client1 = make_shared<Client>();
    std::shared_ptr<Vacation> vacation1 = client1->constructPlanner(10, "成都万达瑞华中心",
            "成都大熊猫繁育研究基地","与大熊猫互动", builder);
    showPlanner(vacation1);

    cout << "第二位游客的安排:" << endl;
    std::shared_ptr<Client> client2 = make_shared<Client>();
    std::shared_ptr<Vacation> vacation2 = client1->constructPlanner(5, "武汉万达瑞华酒店",
            "武汉黄鹤楼公园","参观武汉大学", builder);
    showPlanner(vacation2);

    return 0;
}
显示结果:

在这里插入图片描述


欢迎关注公众号:c_302888524
发送:“设计模式:可复用面向对象软件的基础” 获取电子书
在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值