建造者模式的UML图:
[抽象建造者]-------[具体建造者]
↑ |
[指挥者]-----[产品] <-|
建造者模式的实现步骤:
建造者模式的示例代码与解析:
以汽车制造为例,首先定义一个抽象建造者接口:
class CarBuilder {
public:
virtual void buildEngine() = 0;
virtual void buildBody() = 0;
virtual void buildWheels() = 0;
virtual Car getProduct() = 0;
};
接下来,创建具体建造者类,实现抽象建造者接口:
class SedanCarBuilder : public CarBuilder {
private:
Car car;
public:
void buildEngine() override {
car.setEngine("Sedan engine");
}
void buildBody() override {
car.setBody("Sedan body");
}
void buildWheels() override {
car.setWheels(4);
}
Car getProduct() override {
return car;
}
};
定义指挥者类,用于控制建造过程:
class CarDirector {
private:
CarBuilder *builder;
public:
void setBuilder(CarBuilder *builder) {
this->builder = builder;
}
Car construct() {
builder->buildEngine();
builder->buildBody();
builder->buildWheels();
return builder->getProduct();
}
};
创建产品类,表示最终需要组装的复杂对象:
class Car {
private:
string engine;
string body;
int wheels;
public:
void setEngine(const string &engine) { this->engine = engine; }
void setBody(const string &body) { this->body = body; }
void setWheels(int wheels) { this->wheels = wheels; }
};
客户端通过指挥者类创建和组装产品:
int main() {
CarBuilder *builder = new SedanCarBuilder();
CarDirector director;
director.setBuilder(builder);
Car car = director.construct();
delete builder;
return 0;
}
设计图形用户界面组件: 建造者模式非常适合用于创建具有复杂构建过程的图形用户界面(GUI)组件。例如,一个复杂的窗口界面可能包括菜单栏、工具栏、侧边栏和主内容区等多个部分。每个部分又可以由多个子组件构成。通过使用建造者模式,可以将这些组件的创建过程分解成多个步骤,分别构建各个部分,并将它们组合起来形成完整的界面。
在这种情况下,客户端只需要知道如何使用建造者接口来指定界面的构建过程,而无需关心界面中各个组件的具体实现。此外,通过替换具体建造者,可以轻松地实现不同样式和主题的界面,从而提高代码的复用性和扩展性。
构建游戏角色与场景:
建造者模式也适用于构建游戏中的角色和场景。游戏中的角色可能有多种属性,如姓名、生命值、魔法值、武器和防具等。同样,游戏场景可能包括地形、天气、照明和背景音乐等多个因素。这些属性和因素在创建角色和场景时可能需要不同的设置和组合。
使用建造者模式,可以将角色和场景的构建过程分解为多个步骤,每个步骤负责创建或设置一个属性或因素。例如,创建角色时,首先为其分配姓名,然后设置生命值、魔法值,接着为角色分配武器和防具。通过这种分步构建的方式,可以轻松地创建具有不同属性和特点的角色,同时保证构建过程的可控性和灵活性。
对于场景构建,建造者模式可以帮助创建不同风格的场景,例如森林、沙漠、城市等。通过替换具体建造者,可以轻松地为游戏添加新的场景和风格,从而提高代码的可复用性和扩展性。
在这些应用场景中,客户端代码只需关注如何使用建造者接口来指定角色和场景的构建过程,而无需关心具体实现细节。这样一来,就可以将创建复杂对象的逻辑与具体实现解耦,提高代码的可维护性。
生成文档与报告:
建造者模式适用于生成具有复杂结构和格式的文档和报告。这些文档和报告可能包括多个部分,如标题、正文、引用、图表、注释等。根据具体需求,这些部分可能以不同的顺序组合在一起,或者以特定的格式和样式进行排版。
使用建造者模式,可以将文档和报告的构建过程分解为多个步骤。例如,在创建报告时,可以先设置标题,然后添加正文,接着插入引用和图表,最后添加注释。这种分步构建的方式允许客户端灵活地定制文档和报告的内容、结构和格式。
同时,通过将构建过程与具体实现分离,建造者模式使得可以为不同类型的文档和报告提供不同的建造者。例如,可以创建一个用于生成HTML文档的建造者,以及一个用于生成PDF报告的建造者。客户端只需根据需要选择适当的建造者,就可以轻松地生成各种类型的文档和报告。
总之,在生成文档与报告的应用场景中,建造者模式有助于实现复杂对象的灵活构建和代码的解耦。这有利于提高代码的可维护性、可复用性和扩展性。
建造者模式与单例模式的比较
建造者模式和单例模式都是创建型设计模式,但它们解决的问题和关注的焦点不同。建造者模式关注如何将复杂对象的构建过程分解为多个步骤,以实现灵活的对象创建和代码解耦。而单例模式关注如何确保一个类只有一个实例,并提供一个全局访问点。简单来说,建造者模式用于创建复杂对象,而单例模式用于控制类的实例化。
建造者模式与原型模式的比较
建造者模式和原型模式都属于创建型设计模式。建造者模式主要用于构建具有多个部分的复杂对象,通过多个步骤来创建对象。原型模式主要用于创建新对象的过程中,克隆已有对象的状态和属性,避免了昂贵的创建和初始化过程。原型模式适用于创建成本高昂且状态相似的对象,而建造者模式更关注对象构建过程的灵活性和可控性。
建造者模式与抽象工厂模式的比较
建造者模式和抽象工厂模式都是创建型设计模式,它们都关注对象的创建过程。建造者模式将复杂对象的构建过程分解为多个步骤,使得客户端可以灵活地创建复杂对象。抽象工厂模式为创建一系列相关或相互依赖的对象提供了一个接口,使得客户端在不关心具体类的情况下创建对象。
建造者模式更关注对象创建过程中的细节和步骤,适用于构建具有多个部分的复杂对象。抽象工厂模式关注一组相关对象的创建,适用于创建具有相互依赖关系的对象。在某些情况下,这两种模式可以结合使用。例如,可以使用抽象工厂模式创建一组建造者对象,然后使用建造者模式构建复杂对象。
#include
#include
class GUIComponent {
public:
virtual void draw() const = 0;
};
class Button : public GUIComponent {
public:
void draw() const override {
std::cout << "Drawing button" << std::endl;
}
};
class Label : public GUIComponent {
public:
void draw() const override {
std::cout << "Drawing label" << std::endl;
}
};
class GUIBuilder {
public:
virtual ~GUIBuilder() = default;
virtual GUIComponent* buildButton() = 0;
virtual GUIComponent* buildLabel() = 0;
};
class ConcreteGUIBuilder : public GUIBuilder {
public:
GUIComponent* buildButton() override {
return new Button();
}
GUIComponent* buildLabel() override {
return new Label();
}
};
class GUI {
public:
void addComponent(GUIComponent* component) {
components.push_back(component);
}
void draw() const {
for (const auto& component : components) {
component->draw();
}
}
private:
std::vector<GUIComponent*> components;
};
int main() {
ConcreteGUIBuilder builder;
GUI gui;
gui.addComponent(builder.buildButton());
gui.addComponent(builder.buildLabel());
gui.draw();
return 0;
}
#include
#include
class Config {
public:
void addSetting(const std::string& key, const std::string& value) {
settings[key] = value;
}
void print() const {
for (const auto& setting : settings) {
std::cout << setting.first << ": " << setting.second << std::endl;
}
}
private:
std::map<std::string, std::string> settings;
};
class ConfigBuilder {
public:
virtual ~ConfigBuilder() = default;
virtual void buildSetting(const std::string& key, const std::string& value) = 0;
virtual Config* getConfig() = 0;
};
class ConcreteConfigBuilder : public ConfigBuilder {
public:
void buildSetting(const std::string& key, const std::string& value) override {
config.addSetting(key, value);
}
Config* getConfig() override {
return &config;
}
private:
Config config;
};
int main() {
ConcreteConfigBuilder builder;
builder.buildSetting("username", "admin");
builder.buildSetting("password", "123456");
Config* config = builder.getConfig();
config->print();
return 0;
}
#include
#include
#include
class XMLNode {
public:
XMLNode(const std::string& name) : name(name) {}
void addAttribute(const std::string& key, const std::string& value) {
attributes[key] = value;
}
void addChild(XMLNode* node) {
children.push_back(node);
}
void print(const std::string& indent = "") const {
std::cout << indent << "<" << name;
for (const auto& attribute : attributes) {
std::cout << " " << attribute.first << "=\"" << attribute.second << "\"";
}
std::cout << ">" << std::endl;
for (const auto& child : children) {
child->print(indent + " ");
}
std::cout << indent << "" << name << ">" << std::endl;
}
private:
std::string name;
std::map<std::string, std::string> attributes;
std::vector<XMLNode*> children;
};
class XMLBuilder {
public:
virtual ~XMLBuilder() = default;
virtual XMLNode* buildNode(const std::string& name) = 0;
};
class ConcreteXMLBuilder : public XMLBuilder {
public:
XMLNode* buildNode(const std::string& name) override {
return new XMLNode(name);
}
};
int main() {
ConcreteXMLBuilder builder;
XMLNode* root = builder.buildNode("root");
root->addAttribute("version", "1.0");
XMLNode* child1 = builder.buildNode("child1");
child1->addAttribute("key", "value");
XMLNode* child2 = builder.buildNode("child2");
root->addChild(child1);
root->addChild(child2);
root->print();
return 0;
}
#include
#include
#include
class SQLBuilder {
public:
virtual ~SQLBuilder() = default;
virtual SQLBuilder& select(const std::string& column) = 0;
virtual SQLBuilder& from(const std::string& table) = 0;
virtual SQLBuilder& where(const std::string& condition) = 0;
virtual std::string build() = 0;
};
class ConcreteSQLBuilder : public SQLBuilder {
public:
SQLBuilder& select(const std::string& column) override {
columns.push_back(column);
return *this;
}
SQLBuilder& from(const std::string& table) override {
this->table = table;
return *this;
}
SQLBuilder& where(const std::string& condition) override {
conditions.push_back(condition);
return *this;
}
std::string build() override {
std::string sql = "SELECT ";
for (size_t i = 0; i < columns.size(); ++i) {
sql += columns[i];
if (i < columns.size() - 1) {
sql += ", ";
}
}
sql += " FROM " + table;
if (!conditions.empty()) {
sql += " WHERE ";
for (size_t i = 0; i < conditions.size(); ++i) {
sql += conditions[i];
if (i < conditions.size() - 1) {
sql += " AND ";
}
}
}
return sql;
}
private:
std::vector<std::string> columns;
std::string table;
std::vector<std::string> conditions;
};
int main() {
ConcreteSQLBuilder sqlBuilder;
std::string sql = sqlBuilder.select("name")
.select("age")
.from("users")
.where("age > 18")
.where("country = 'US'")
.build();
std::cout << "SQL Query: " << sql << std::endl;
return 0;
}
#include
#include
#include
class HtmlElement {
public:
virtual std::string str() const = 0;
};
class HtmlText : public HtmlElement {
public:
explicit HtmlText(const std::string& text) : text(text) {}
std::string str() const override {
return text;
}
private:
std::string text;
};
class HtmlTag : public HtmlElement {
public:
HtmlTag& addElement(const HtmlElement& element) {
elements.push_back(element.str());
return *this;
}
protected:
std::vector<std::string> elements;
};
class HtmlHead : public HtmlTag {
public:
std::string str() const override {
std::string result = "\n";
for (const auto& e : elements) {
result += " " + e + "\n";
}
result += "";
return result;
}
};
class HtmlBody : public HtmlTag {
public:
std::string str() const override {
std::string result = "\n";
for (const auto& e : elements) {
result += " " + e + "\n";
}
result += "";
return result;
}
};
class HtmlDocumentBuilder {
public:
HtmlDocumentBuilder& addHeadElement(const HtmlElement& element) {
head.addElement(element);
return *this;
}
HtmlDocumentBuilder& addBodyElement(const HtmlElement& element) {
body.addElement(element);
return *this;
}
std::string build() {
return "\n\n" + head.str() + "\n" + body.str() + "\n";
}
private:
HtmlHead head;
HtmlBody body;
};
int main() {
HtmlDocumentBuilder builder;
std::string html = builder.addHeadElement(HtmlText("My Title "))
.addBodyElement(HtmlText("Welcome to my website
"))
.addBodyElement(HtmlText("This is a simple example.
"))
.build();
std::cout << "HTML Document: \n" << html << std::endl;
return 0;
}
由于3D模型构建涉及到很多图形学和几何学的知识,因此在此仅提供一个简化的示例,主要用于演示建造者模式的使用。
#include
#include
#include
class ModelPart {
public:
virtual std::string getName() const = 0;
};
class ModelCube : public ModelPart {
public:
std::string getName() const override {
return "Cube";
}
};
class ModelSphere : public ModelPart {
public:
std::string getName() const override {
return "Sphere";
}
};
class Model3DBuilder {
public:
Model3DBuilder& addPart(const ModelPart& part) {
parts.push_back(part.getName());
return *this;
}
std::string build() {
std::string result = "3D Model:\n";
for (const auto& part : parts) {
result += " " + part + "\n";
}
return result;
}
private:
std::vector<std::string> parts;
};
int main() {
Model3DBuilder builder;
std::string model3D = builder.addPart(ModelCube())
.addPart(ModelSphere())
.addPart(ModelCube())
.build();
std::cout << model3D << std::endl;
return 0;
}
#include
#include
#include
class Message {
public:
std::string content;
std::string type;
};
class MessageQueueBuilder {
public:
MessageQueueBuilder& addMessage(const Message& message) {
messages.push_back(message);
return *this;
}
std::vector<Message> build() {
return messages;
}
private:
std::vector<Message> messages;
};
class Protocol {
public:
std::string name;
std::string version;
};
class ProtocolBuilder {
public:
ProtocolBuilder& setName(const std::string& name) {
protocol.name = name;
return *this;
}
ProtocolBuilder& setVersion(const std::string& version) {
protocol.version = version;
return *this;
}
Protocol build() {
return protocol;
}
private:
Protocol protocol;
};
int main() {
MessageQueueBuilder messageQueueBuilder;
std::vector<Message> messageQueue = messageQueueBuilder.addMessage({"Hello", "Text"})
.addMessage({"Goodbye", "Text"})
.build();
for (const auto& message : messageQueue) {
std::cout << message.content << " - " << message.type << std::endl;
}
ProtocolBuilder protocolBuilder;
Protocol protocol = protocolBuilder.setName("HTTP")
.setVersion("1.1")
.build();
std::cout << "Protocol: " << protocol.name << ", Version: " << protocol.version << std::endl;
return 0;
}
#include
#include
#include
class DataStructure {
public:
std::map<std::string, std::string> data;
};
class DataStructureBuilder {
public:
DataStructureBuilder& addEntry(const std::string& key, const std::string& value) {
dataStructure.data[key] = value;
return *this;
}
DataStructure build() {
return dataStructure;
}
private:
DataStructure dataStructure;
};
class TemplateCode {
public:
std::string code;
};
class TemplateCodeBuilder {
public:
TemplateCodeBuilder& appendLine(const std::string& line) {
templateCode.code += line + "\n";
return *this;
}
TemplateCode build() {
return templateCode;
}
private:
TemplateCode templateCode;
};
int main() {
DataStructureBuilder dataStructureBuilder;
DataStructure dataStructure = dataStructureBuilder.addEntry("Name", "Alice")
.addEntry("Age", "30")
.build();
for (const auto& entry : dataStructure.data) {
std::cout << entry.first << ": " << entry.second << std::endl;
}
TemplateCodeBuilder templateCodeBuilder;
TemplateCode templateCode = templateCodeBuilder.appendLine("#include " )
.appendLine("int main() {")
.appendLine(" std::cout << \"Hello, world!\" << std::endl;")
.appendLine(" return 0;")
.appendLine("}")
.build();
std::cout << "Generated Template Code: \n" << templateCode.code << std::endl;
return 0;
}