- C++设计模式笔记(10) - Prototype 原型模式:
https://blog.csdn.net/mofan6930/article/details/104998680
- 参考课程:《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
发送:“设计模式:可复用面向对象软件的基础” 获取电子书