网站如何在百度上搜索到,青岛商业网站建设,苏州园区属于哪个区,涡阳做网站概述 在实际项目中#xff0c;我们有时会遇到需要创建复杂对象的情况。这些对象可能包含多个组件或属性#xff0c;而且每个组件都有自己的配置选项。如果直接使用构造函数或前面介绍的工厂方法来创建这样的对象#xff0c;可能会导致以下两个严重问题。 1、参数过多。当一个…概述 在实际项目中我们有时会遇到需要创建复杂对象的情况。这些对象可能包含多个组件或属性而且每个组件都有自己的配置选项。如果直接使用构造函数或前面介绍的工厂方法来创建这样的对象可能会导致以下两个严重问题。 1、参数过多。当一个类有很多可选参数时构造函数可能会变得非常庞大难以维护。此外调用方必须记住哪些参数是必需的哪些是可选的这在一定程度上增加了出错的风险。 2、代码冗余。如果每次创建对象都需要传递大量的参数那么代码将会变得冗长、复杂且难以理解。即使有些参数有默认值调用者仍然需要为所有参数提供值。 相比之下建造者模式提供了更好的解决方案。它通过引入一个专门的建造者类来逐步构建对象直到所有的必要部分都被设置完毕。这样不仅可以简化对象的创建过程还可以提高代码的可读性和可维护性。 餐厅点餐是运用建造者模式的一个典型例子菜单上有多种套餐组合但每个套餐的具体内容可能不同服务员会根据我们的选择逐步记录下我们想要的食物和饮料最后再把这些信息传递给厨房。在这个过程中服务员扮演了“导演”的角色而每道菜的厨师则是具体的“建造者”他们负责按照订单的要求制作食物。 基本原理 建造者模式的核心思想是将一个复杂对象的构建过程与其表示分离从而使得同样的构建过程可以创建不同的表示。它提供了一种分步骤构造复杂对象的方法避免了大型构造函数带来的问题并且提高了代码的可读性和可维护性。建造者模式包括如下四个核心组件。 1、产品类。代表要创建的复杂对象它可以是一个具体的产品实例也可以是一系列相关属性的集合。产品类通常包含多个组成部分每个部分都有自己的配置选项。 2、抽象建造者。定义了创建产品各个部分的接口它是所有具体建造者的基类或接口声明了一系列用于组装产品的抽象方法。这些方法定义了如何构建产品的不同部分但不涉及具体的实现逻辑。 3、具体建造者。实现了抽象建造者接口提供了构建产品的具体实现。每个具体建造者都对应一种特定的产品配置或类型负责按照预定规则组装出完整的产品。通常情况下具体建造者还会提供一个类似GetResult的方法来获取最终构建的产品对象。 4、导演类。导演类负责协调各个具体建造者的执行顺序它不直接参与产品的构建而是调用建造者的方法来组织构建过程。它可以根据不同的需求选择合适的建造者并控制构建的流程。 基于上面的核心组件建造者模式的实现主要有以下五个步骤。 1、定义产品类。创建一个代表最终产品的类它包含了所有与产品相关的属性。 2、定义抽象建造者。定义一个接口或抽象类声明一组用于构建产品的方法。这些方法定义了如何设置产品的各个部分但不涉及具体的实现细节。 3、实现具体建造者。根据需要创建多个具体建造者类每个类都实现了抽象建造者接口。每个具体建造者负责按照特定的规则组装出完整的产品并提供GetResult方法来返回最终构建的产品对象。 4、创建导演类。定义一个导演类它负责调用具体建造者的方法来组织构建过程。导演类不直接参与产品的构建而是充当协调者的角色确保构建过程按照预期进行。 5、编写应用层代码。在应用层代码中首先选择合适的具体建造者并将其传递给导演类。导演类会根据预设的构建流程调用建造者的方法逐步构建出最终的产品对象。最后应用层可以从建造者那里获取到完全配置好的产品实例。 实战解析 在下面的实战代码中我们使用建造者模式模拟了餐厅点餐的应用场景。 首先我们定义了产品类COrder。COrder类代表最终的订单对象它包含了主菜、饮料、甜点以及额外添加的项目。 然后我们定义了抽象建造者COrderBuilder。COrderBuilder是一个接口或抽象类声明了一系列用于设置订单各个部分的方法。每个具体建造者都将实现这些方法以按照特定规则组装出完整的订单。 接下来我们实现了具体建造者CStandardMealBuilder和CVegetarianMealBuilder分别表示创建标准套餐和素食套餐。每个具体建造者都实现了COrderBuilder接口并提供了构建特定类型订单的具体逻辑。 我们还创建了导演类CWaiter它负责协调各个建造者的执行顺序。它不直接参与订单的构建而是调用建造者的方法来组织构建过程这样可以确保构建过程的一致性和灵活性。 最后在main函数中我们首先选择了CStandardMealBuilder来构建一个标准套餐并通过CWaiter类来指导构建过程。紧接着我们选择了CVegetarianMealBuilder来构建一个素食套餐。最后我们打印了两个订单的具体内容并进行了清理工作。
#include iostream
#include string
#include vectorusing namespace std;// 定义产品类订单对象
class COrder
{
public:void SetMainDish(const string strDish){m_strMainDish strDish;}void SetDrink(const string strDrink){m_strDrink strDrink; }void SetDessert(const string strDessert){m_strDessert strDessert;}void AddExtra(const string strExtra){m_vctExtras.push_back(strExtra);}void Print() const{cout Your order contains: endl;if (!m_strMainDish.empty()){cout Main dish: m_strMainDish endl;}if (!m_strDrink.empty()){cout Drink: m_strDrink endl;}if (!m_strDessert.empty()){cout Dessert: m_strDessert endl;}if (!m_vctExtras.empty()){cout Extras: endl;for (const auto extra : m_vctExtras){cout extra endl;}}}private:string m_strMainDish; // 主菜string m_strDrink; // 饮料string m_strDessert; // 甜点vectorstring m_vctExtras; // 额外项
};// 定义抽象建造者
class COrderBuilder
{
public:COrderBuilder(){m_pOrder new COrder();}virtual ~COrderBuilder() {}virtual void BuildMainDish() 0;virtual void BuildDrink() 0;virtual void BuildDessert() 0;virtual void AddExtras() 0;virtual COrder* GetResult(){return m_pOrder; }protected:COrder* m_pOrder;
};// 实现具体建造者标准套餐建造者
class CStandardMealBuilder : public COrderBuilder
{
public:void BuildMainDish() override{m_pOrder-SetMainDish(Roast Chicken);}void BuildDrink() override{m_pOrder-SetDrink(Cola);}void BuildDessert() override{m_pOrder-SetDessert(Ice Cream);}void AddExtras() override{m_pOrder-AddExtra(Potato Fries);}
};// 实现具体建造者素食套餐建造者
class CVegetarianMealBuilder : public COrderBuilder
{
public:void BuildMainDish() override{m_pOrder-SetMainDish(Vegetable Curry);}void BuildDrink() override{m_pOrder-SetDrink(Lemonade);}void BuildDessert() override{m_pOrder-SetDessert(Fruit Salad);}void AddExtras() override{m_pOrder-AddExtra(Breadsticks);}
};// 创建导演类服务员
class CWaiter
{
public:void Construct(COrderBuilder* pBuilder){pBuilder-BuildMainDish();pBuilder-BuildDrink();pBuilder-BuildDessert();pBuilder-AddExtras();}
};int main()
{CWaiter waiter;// 选择标准套餐COrderBuilder* pBuilder new CStandardMealBuilder();waiter.Construct(pBuilder);COrder* pStandardOrder pBuilder-GetResult();cout ***** Standard Meal ***** endl;pStandardOrder-Print();cout endl;delete pBuilder;// 选择素食套餐pBuilder new CVegetarianMealBuilder();waiter.Construct(pBuilder);COrder* pVegetarianOrder pBuilder-GetResult();cout ***** Vegetarian Meal ***** endl;pVegetarianOrder-Print();delete pBuilder;// 清理delete pStandardOrder;delete pVegetarianOrder;return 0;
} 总结 对于那些需要很多参数的对象创建尤其是这些参数大多数是可选的时候使用建造者模式可以让代码更加易读、易于维护。相比长串的构造函数参数列表建造者模式提供了更自然的接口来逐步设定属性。 但建造者模式也引入了额外的类即具体的建造者因此会稍微增加系统的复杂度和整体大小。对于简单的对象创建这种模式可能显得过于繁琐。如果要添加新的产品就需要修改现有的建造者接口或创建新的建造者子类这可能会影响现有代码的稳定性。另外如果建造者负责多个不同类型的对象创建可能会导致建造者类变得臃肿承担过多责任从而违背了单一职责原则。