作者: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