文章目录
- 建造者模式
- 为什么使用建造者模式
- 建造者模式实现步骤
- 实现示例
- 建造者模式优缺点
建造者模式
建造者模式(Builder Pattern)是面向对象设计模式中的一种,主要用于创建复杂对象。这种模式将对象的构建过程与其表示分离,允许用户通过相同的构建过程创建不同的表示。以下是建造者模式的一些关键概念:
- 产品(Product):
这是最终要创建的复杂对象。产品可能由多个组成部分构成,这些部分可以有不同的表现形式。- 抽象建造者(Builder):
定义了一个用于创建复杂对象的接口,但并不涉及具体的部件和它们的装配方式。它通常包含一系列用于构建产品各个部分的方法。- 具体建造者(Concrete Builder):
实现了抽象建造者接口,负责构建并装配各个部分。具体建造者类通常包含了构建产品各个部分的业务逻辑。- 指挥者(Director):
使用建造者对象中的方法来创建产品对象。指挥者不关心具体产品是如何被构建的,它只负责指导建造者去构建产品。有时,指挥者的职责可以内嵌到客户端代码中。
为什么使用建造者模式
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
建造者模式(Builder Pattern)主要在以下几种情况下使用,以解决特定的设计问题:
- 对象构造复杂:
当一个对象的构造过程复杂,涉及到很多不同的选项或配置,而且这些选项之间可能存在依赖关系时,使用建造者模式可以将构造过程分解为一系列小步骤,每个步骤负责设置对象的一部分属性。这使得构造过程更清晰,避免了构造函数中出现大量参数的情况,也使得对象的构造更为灵活。- 对象具有多种变体:
如果一个对象可能有多种不同的配置或表示形式,而这些配置或表示在构造时就已经确定,那么可以使用建造者模式来创建这些变体。通过不同的具体建造者,可以构造出不同配置的对象实例。- 构造过程独立于部件:
建造者模式使构建过程和产品对象的表示相分离,这意味着即使构建过程改变,也不影响产品对象的表示,反之亦然。这有助于维护代码的稳定性和可扩展性。- 控制构建过程的顺序:
某些情况下,对象的构建顺序很重要,而这个顺序可能会随时间变化。建造者模式通过将构建过程委托给Director(指挥者)类来管理,可以很容易地调整构建顺序,而无需修改建造者本身。- 减少重复代码:
当构建相似但不完全相同的产品对象时,建造者模式可以减少重复代码。不同的建造者可以共享相同的构建逻辑,只是在某些步骤上有所不同。- 易于扩展和维护:
如果未来需要增加新的产品特性,只需添加新的建造者类,而无需修改现有的建造者或产品类。这使得系统更容易适应需求变化。
例如,在软件开发中,创建一个复杂的数据库连接工厂可能需要指定不同的数据库类型、驱动程序、连接字符串、身份验证信息等。使用建造者模式,你可以逐步设定这些参数,同时保持代码的清晰和可维护性。
建造者模式实现步骤
1.提供抽象建造者类: 为创建产品各个部分,统一抽象接口
2.提供具体建造者类:具体实现抽象建造者各个部件的接口
3.提供多个具体产品类:具体的创建产品的各个部分
4.提供一个指挥类:负责安排和调度复杂对象的各个建造过程
实现示例
//电脑组装:显示器、鼠标、键盘、主机(主机又包括cpu、显卡、主板等)
//1.找到店铺老板告诉需求
//2.客服安排技术员工组装
//3.产品组装完成
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//电脑组装:显示器、鼠标、键盘、主机(主机又包括cpu、显卡、主板等)
//1.找到店铺老板告诉需求
//2.客服安排技术员工组装
//3.产品组装完成
//抽象产品类
class AbstractProduct
{
public:
virtual void SetDisplayer(string displayer) = 0;
virtual void SetMouse(string mouse) = 0;
virtual void SetKeyBoard(string keyBoard) = 0;
virtual void SetHost(string host) = 0;
virtual void Show() = 0;
};
//具体产品类
class Computer :public AbstractProduct
{
void SetDisplayer(string displayer)
{
m_list.push_back(displayer);
}
void SetMouse(string mouse)
{
m_list.push_back(mouse);
}
void SetKeyBoard(string keyBoard)
{
m_list.push_back(keyBoard);
}
void SetHost(string host)
{
m_list.push_back(host);
}
void Show()
{
cout << "电脑配置结果:" << endl;
for (auto v : m_list)
{
cout << v << endl;
}
}
vector<string> m_list;
};
//抽象建造者类
class AbstractBuilder
{
public:
AbstractBuilder():product(new Computer) {}
//抽象构造过程
virtual void BuildDisplayer(string displayer) = 0;
virtual void BuildMouse(string mouse) = 0;
virtual void BuildKeyBoard(string keyBoard) = 0;
virtual void BuildHost(string host) = 0;
AbstractProduct* Getproduct()
{
return product;
}
protected:
AbstractProduct* product;
};
//具体的建造者类--->组装电脑的技术员
class ConcreteBuilder :public AbstractBuilder
{
public:
void BuildDisplayer(string displayer)
{
product->SetDisplayer(displayer);
}
void BuildMouse(string mouse)
{
product->SetMouse(mouse);
}
void BuildKeyBoard(string keyBoard)
{
product->SetKeyBoard(keyBoard);
}
void BuildHost(string host)
{
product->SetHost(host);
}
};
//指挥者类
class Director
{
public:
Director(AbstractBuilder* pBuilder) :pBuilder(pBuilder) {}
AbstractProduct* createProduct(string displayer, string mouse, string keyBoard, string host)
{
pBuilder->BuildDisplayer(displayer);
pBuilder->BuildMouse(mouse);
pBuilder->BuildKeyBoard(keyBoard);
pBuilder->BuildHost(host);
return pBuilder->Getproduct();
}
private:
AbstractBuilder* pBuilder;
};
int main()
{
AbstractBuilder* pB = new ConcreteBuilder;
Director* pD = new Director(pB);
AbstractProduct* computer = pD->createProduct("华为显示器", "牧马人鼠标", "雷蛇键盘", "外星人");
computer->Show();
return 0;
}
建造者模式优缺点
优点
-
封装性好,构建和表示分离
-
扩展性好,各个具体的建造者相互独立,有利于系统的解耦
-
控制细节风险,客户端无需详知细节,建造者细化创建过程
缺点
-
产品的组成部分必须相同,这限制了其使用范围
-
产品内部发生变化,建造者需同步修改,后期维护成本较大