设计模式-04 设计模式-Builder

ops/2024/11/15 6:09:01/
设计模式-04 设计模式-Builder

1.定义

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你使用不同的构建步骤来创建复杂的对象。
建造者模式的定义是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

                                       指挥者|/         \\/           \\/             \\具体建造者 A       具体建造者 B|               |/               |_______________/_______________|______________|                                              ||                                              ||                                              |_______|______________________________________________|____|                                                          ||                      已构建的产品                         ||__________________________________________________________|

在这个 ASCII 图中:

  • 指挥者负责协调建造过程,它告诉建造者要创建哪些部分以及如何组装它们。
  • 具体建造者代表不同的产品类型或变体。每个具体建造者负责构建产品的一个或多个部分。
  • 已构建的产品是建造过程的结果。

建造过程如下:

  1. 指挥者创建一个具体建造者。
  2. 指挥者调用具体建造者的构建方法来创建产品的不同部分。
  3. 指挥者可以调用多个具体建造者来创建复杂的产品结构。
  4. 一旦所有部分都构建完成,指挥者调用具体建造者的获取产品方法来检索已构建的产品。
2.内涵


换句话说,建造者模式将对象的构建过程与对象的表示分离。这使得你可以使用相同的构建过程来创建不同类型的对象,而无需更改构建代码本身。

建造者模式包含以下角色:

  • 建造者(Builder):负责创建和组装最终的对象。
  • 具体建造者(Concrete Builder):实现建造者接口,并负责创建和组装最终对象的特定部分。
  • 指挥者(Director):负责协调建造过程,它告诉建造者要创建哪些部分以及如何组装它们。
  • 产品(Product):最终创建的对象。
3.案例对比

不用 Builder 设计模式

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
#include <tuple>
#include <sstream>
#include <memory>
using namespace std;/***  <p>hello</p><ul> <li>hello</li> <li>world</li></ul>* @return*/
int main() {auto text= "hello";string output;output+="<p>";output+=text;output+="</p>";cout<<output<<endl;string words[] = {"hello", "world"};ostringstream oss;oss<<"<ul>";for(auto w: words){oss<<" <li>" << w <<"</li>";}oss<<"</ul>";cout<<oss.str()<<endl;return 0;
}


使用 Builder 设计模式

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <fstream>
#include <tuple>
#include <sstream>
#include <memory>
using namespace std;struct HtmlElement
{string name, text;vector<HtmlElement> elements;const size_t indent_size =2;HtmlElement(){}HtmlElement(const string& name,const string& text):name(name),text(text){}string str(int intent = 0)const{ostringstream oss;string i(indent_size*intent, ' ');oss << i << "<" << name << ">" << endl;if(text.size() > 0){oss<<string(indent_size*(intent + 1), ' ') << text <<endl;}for(const auto& e:elements) {oss << e.str(intent + 1);}oss<<i << "</" << name << ">" << endl;return oss.str();}};struct HtmlBuilder
{HtmlElement root;HtmlBuilder(string rootname){root.name = rootname;}void add_child(string child_name, string child_text){HtmlElement e{child_name, child_text};root.elements.emplace_back(e);}string str() const {return root.str();}
};int main() {HtmlBuilder builder ("ul");builder.add_child("li", "hello");builder.add_child("li", "world");builder.add_child("li", "hello");cout << builder.str() << endl;return 0;
}

4.注意事项

在实际使用建造者模式时,需要注意以下几点和原则:

1. 分离接口和实现

建造者模式的核心原则是将对象的构建过程与它的表示分离。因此,建造者接口应该只定义创建和组装对象所需的方法,而具体的实现细节应该委托给具体建造者。

2. 确保建造者产品的一致性

指挥者负责协调建造过程,它告诉建造者要创建哪些部分以及如何组装它们。为了确保建造出的产品是一致的,指挥者需要使用相同的建造者接口来调用所有具体建造者。

3. 灵活性和可扩展性

建造者模式的优点之一是它的灵活性和可扩展性。你可以轻松地添加新的具体建造者来创建新的对象类型,而无需修改现有代码。这使得建造者模式非常适合需要创建各种不同对象的场景。

4. 避免创建不必要的具体建造者

虽然建造者模式允许你创建任意数量的具体建造者,但重要的是要避免创建不必要的具体建造者。每个具体建造者都应该代表一种不同的对象类型或变体。

5. 考虑使用不可变对象

对于需要不可变对象的场景,你可以考虑使用不可变对象来表示产品。这可以防止在构建过程之后意外修改对象。

6. 性能考虑

如果性能是一个问题,你需要仔细考虑建造者模式的开销。创建和销毁大量的具体建造者可能会对性能产生影响。

7. 何时使用建造者模式

建造者模式最适合用于创建复杂的对象,这些对象需要经过多个构建步骤才能创建。例如,它可以用在创建文档、GUI 控件或 Web 页面等对象中。


个人觉得如果对象很简单,并且不需要经过多个构建步骤,则建造者模式可能过于复杂。在这种情况下,可以使用更简单的创建模式,例如工厂方法模式或单例模式会更简单。


5.最佳实践


建造者模式的最佳实践包括:

  • 使用不可变对象:对于需要不可变对象的场景,使用不可变对象来表示产品可以防止在构建过程之后意外修改对象。
  • 使用分层建造者:对于复杂的对象,可以考虑使用分层建造者。分层建造者将构建过程分解成更小的步骤,并允许你创建嵌套的对象结构。
  • 使用流式 API:对于需要创建大量相似对象的场景,可以使用流式 API 来简化构建过程。流式 API 允许你将构建步骤链接在一起,并使用链式语法来创建对象。
  • 考虑使用生成器函数:在某些情况下,使用生成器函数可以简化建造者模式的实现。生成器函数可以让你一步一步地构建对象,而无需显式地创建和销毁具体建造者。
  • 避免创建不必要的具体建造者:每个具体建造者都应该代表一种不同的对象类型或变体。避免创建不必要的具体建造者,因为这会增加代码的复杂性和维护成本。
  • 确保建造者产品的一致性:指挥者负责协调建造过程,它告诉建造者要创建哪些部分以及如何组装它们。为了确保建造出的产品是一致的,指挥者需要使用相同的建造者接口来调用所有具体建造者。
6.总结

如果性能是一个问题,你需要仔细考虑建造者模式的开销。创建和销毁大量的具体建造者可能会对性能产生影响。


http://www.ppmy.cn/ops/29425.html

相关文章

IoTDB 入门教程④——数据库用户管理和用户权限管理

文章目录 一、前文二、修改ROOT密码三、用户登录四、查看用户列表五、创建用户六、删除用户七、修改用户八、查看指定用户的权限范围九、添加指定用户的权限范围十、删除指定用户的权限范围十一、参考 一、前文 IoTDB入门教程——导读 本文主要讲述数据库用户管理和用户权限管理…

机器翻译常用指标BLEU

诸神缄默不语-个人CSDN博文目录 文章目录 什么是BLEU指标&#xff1f;BLEU指标的原理BLEU的计算公式BLEU指标的Python实现 什么是BLEU指标&#xff1f; BLEU&#xff08;Bilingual Evaluation Understudy&#xff09;指标是一种评估机器翻译质量的方法&#xff0c;广泛用于自然…

Linux 第十八章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

IOS上线操作

1、拥有苹果开发者账号 2、配置证书&#xff0c;进入苹果开发者官网&#xff08;https://developer.apple.com/&#xff09; 3、点击账户&#xff08;account&#xff09;&#xff0c;然后创建一个唯一的标识符 4、点击"Identifiers"&#xff0c;然后点击"&qu…

设计模式:建造者模式

目录 一&#xff0c;概念 二&#xff0c;不使用建造者有什么麻烦 三&#xff0c;格式 一&#xff0c;概念 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;用于将复杂对象的构建与其表示分离&#xff0c;以便同样的构建过程可以创建不同…

CTF(Capture The Flag)编码方式

CTF&#xff08;Capture The Flag&#xff09;比赛中&#xff0c;编码和解码是常见的挑战类别之一&#xff0c;涉及到各种不同的编码方式。以下是一些CTF中可能出现的编码技术列表&#xff1a; Base系列编码&#xff1a; Base16&#xff08;Hexadecimal&#xff09;&#xff1a…

AI图书推荐:用ChatGPT快速创建在线课程

您是否是您领域的专家&#xff0c;拥有丰富的知识和技能可以分享&#xff1f;您是否曾想过创建一个在线课程&#xff0c;但被这个过程吓倒了&#xff1f;那么&#xff0c;是时候把这些担忧放在一边&#xff0c;迈出这一步了&#xff01;有了这本指南和ChatGPT的帮助&#xff0c…

R语言学习—4—数据矩阵及R表示

1、创建向量、矩阵 在R中&#xff0c;c()函数用于创建向量或组合数据对象。它在某些情况下可能会被省略&#xff0c;因为R有一些隐式的向量创建规则。例如&#xff0c;当你使用:操作符创建一个数字序列时&#xff0c;R会自动创建一个向量&#xff0c;所以你不需要显式地调用c()…