设计模式4 - 建造者模式

本文介绍建造者模式,它是创建型模式,用多个简单对象构建复杂对象。阐述其使用场景,即对象内部结构复杂且属性相互依赖。分析了优缺点,还说明了与抽象工厂模式的区别。最后给出UML结构图和C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

使用场景

  • 需要生成的对象具有复杂的内部结构。
  • 需要生成的对象内部属性本身相互依赖。

优缺点

  • 优点:
    1、建造者独立,易扩展。
    2、便于控制细节风险。

  • 缺点:
    1、产品必须有共同点,范围有限制。
    2、如内部变化复杂,会有很多的建造类。

注意事项

与抽象工厂模式的区别是:建造者模式更加关注与零件装配的顺序
在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 。
如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。

UML结构图

在这里插入图片描述

代码实现

packinterface.h
创建抽象类 - 打包; 创建具体类 - 用纸打包、用瓶打包

#include <iostream>
using namespace std;

class Packing   //基类-打包
{
public:
    Packing() {}
    virtual ~Packing() {}

    virtual string pack() = 0;
};

class Wrapper: public Packing   //子类-用纸打包
{
public:
    string pack() { return "Wrapper"; }
};

class Bottle: public Packing    //子类-用瓶打包
{
public:
    string pack() { return "Bottle"; }
};

foodinterface.h
创建抽象类 - 食物; 创建子类 - 汉堡、冷饮;
创建孙子类 - 蔬菜汉堡、鸡肉汉堡、可口可乐、百事可乐

#include "packinterface.h"
#include <string>

class Food  //基类-食物
{
public:
    Food() {}
    virtual ~Food() {}

    virtual Packing * getPack() = 0;
    virtual string getName() = 0;
    virtual float getPrice() = 0;
};

class Burger: public Food   //子类-汉堡,用纸打包
{
public:
    Packing * getPack()
    {
        return new Wrapper();
    }

    virtual string getName() = 0;
    virtual float getPrice() = 0;
};

class ColdDrink: public Food    //子类-冷饮,用瓶打包
{
public:
    Packing * getPack()
    {
        return new Bottle();
    }

    virtual string getName() = 0;
    virtual float getPrice() = 0;
};

class VegBurger: public Burger  //孙子类-蔬菜汉堡
{
public:
    string getName()
    {
        return "Veg Burger";
    }

    float getPrice()
    {
        return 25.0f;
    }
};

class ChickenBurger: public Burger  //孙子类-鸡肉汉堡
{
public:
    string getName()
    {
        return "Chicken Burger";
    }

    float getPrice()
    {
        return 50.5f;
    }
};

class Coke: public ColdDrink    //孙子类-可口可乐
{
public:
    string getName()
    {
        return "Coke";
    }

    float getPrice()
    {
        return 30.0f;
    }
};

class Pepsi: public ColdDrink   //孙子类-百世可乐
{
public:
    string getName()
    {
        return "Pepsi";
    }

    float getPrice()
    {
        return 35.0f;
    }
};

meal.h
创建菜单类 - 可以添加食物到菜单、计算菜单所有食物的价格、展示菜单中的食物

#include "foodinterface.h"
#include <vector>

class Meal
{
public:
    Meal()
    {
        vec.reserve(255);
    }

    void addFoodToVector(Food * food)
    {
        vec.push_back(food);
    }

    float getCost()
    {
        float ret = 0.0;

        for(auto &food: vec)
        {
            ret += food->getPrice();
        }

        return ret;
    }

    void showFoods()
    {
        for(auto &food: vec)
        {
            cout << "--------------------------" << endl;
            cout << food->getName() << endl;
            cout << food->getPack()->pack() << endl;
            cout << food->getPrice() << endl;
        }
    }

public:
    std::vector<Food *> vec;
};

meakbuilder.h
创建构造菜单类 - 使用菜单类任意组合食物构成一个菜单(套餐)

#include "meal.h"

class MealBuilder
{
public:
    Meal * prepareVegMeal ()
    {
      Meal * meal = new Meal();
      meal->addFoodToVector(new VegBurger());
      meal->addFoodToVector(new Coke());
      return meal;
   }

   Meal * prepareNonVegMeal ()
   {
      Meal * meal = new Meal();
      meal->addFoodToVector(new ChickenBurger());
      meal->addFoodToVector(static_cast<ColdDrink *>(new Pepsi()));
      return meal;
   }
};

main.cpp
实例应用 - 返回一个完整的对象

#include "meakbuilder.h"

int main()
{
    MealBuilder * mealBuilder = new MealBuilder();

    Meal * vegMeal = mealBuilder->prepareVegMeal();
    cout << "Veg Meal" << endl;
    vegMeal->showFoods();
    cout << "Total Cost: " << vegMeal->getCost() << endl;

    Meal * nonVegMeal = mealBuilder->prepareNonVegMeal();
    cout << "\n\nNon-Veg Meal" << endl;
    nonVegMeal->showFoods();
    cout << "Total Cost: " << nonVegMeal->getCost() << endl;

    return 0;
}

运行结果:
Veg Meal
--------------------------
Veg Burger
Wrapper
25
--------------------------
Coke
Bottle
30
Total Cost: 55


Non-Veg Meal
--------------------------
Chicken Burger
Wrapper
50.5
--------------------------
Pepsi
Bottle
35
Total Cost: 85.5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值