实现
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。
我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item 接口和实现 Item 接口的实体类,以及一个表示食物包装的 Packing 接口和实现 Packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。
然后我们创建一个 Meal 类,带有 Item 的 ArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilder。BuilderPatternDemo 类使用 MealBuilder 来创建一个 Meal。
#pragma once
#include <QString>
class Packing {
public:
Packing() {}
virtual ~Packing() {}
virtual QString packMethod() const = 0;
};
class Wrapper : public Packing {
public:
~Wrapper() {}
QString packMethod() const { return "Packing: Wrapper"; }
};
class Bottle : public Packing {
public:
~Bottle() {}
QString packMethod() const { return "Packing: Bottle"; }
};
#pragma once
#include <QString>
#include "Packing.h"
// Item:表示食物的条目,由汉堡和冷饮组成
// 汉堡:蔬菜\鸡肉汉堡(子类),通过纸盒包装(内部实例化纸盒包装);
//
class Item {
public:
Item() {}
virtual ~Item() {}
virtual Packing* packing() const { return nullptr; }
virtual QString name() const { return ""; }
virtual float price() const { return 0.0f; }
};
/*****************汉堡**********************/
class Burger : public Item {
public:
Burger() {}
virtual ~Burger() {}
Packing* packing() const { return new Wrapper; }
// virtual QString name() const = 0;
// virtual float price() const = 0;
};
class VegBurger : public Burger {
public:
VegBurger() {}
virtual ~VegBurger() {}
QString name() const { return "Veg Burger"; }
float price() const { return 15.0f; }
};
class ChickenBurger : public Burger {
public:
ChickenBurger() {}
virtual ~ChickenBurger() {}
QString name() const { return "Chicken Burger"; }
float price() const { return 25.0f; }
};
/******************冷饮*********************/
class ColdDrink : public Item {
public:
ColdDrink() {}
virtual ~ColdDrink() {}
Packing* packing() const { return new Bottle; }
// virtual QString name() const = 0;
// virtual float price() const = 0;
};
class Coke : public ColdDrink {
public:
Coke() {}
virtual ~Coke() {}
QString name() const { return "Coke"; }
float price() const { return 10.0f; }
};
class Pepsi : public ColdDrink {
public:
Pepsi() {}
virtual ~Pepsi() {}
QString name() const { return "Pepsi"; }
float price() const { return 20.0f; }
};
#pragma once
#include <Item.h>
#include <QDebug>
#include <QList>
class Meal {
public:
Meal() { _items.clear(); };
~Meal() {
for (auto item : _items) {
delete item;
item = nullptr;
}
}
void addItem(Item* item) { _items.push_back(item); }
float getCost() {
float cost = 0.0f;
for (const auto& item : _items)
cost += item->price();
return cost;
}
void showItems() {
for (const auto& item : _items) {
qDebug().noquote() << QStringLiteral("Item: %1").arg(item->name());
qDebug().noquote() << QStringLiteral("Packing: %1").arg(item->packing()->packMethod());
qDebug().noquote() << QStringLiteral("Price: %1").arg(item->price());
}
}
private:
QList<Item*> _items;
};
对于菜单创建类,感觉是写死的,应该可以更灵活的组合。
#pragma once
#include "Meal.h"
class MealBuilder {
public:
MealBuilder(){};
Meal prepareVegMeal() {
Meal meal;
meal.addItem(new VegBurger);
meal.addItem(new Coke);
return meal;
}
Meal prepareNonVegMeal() {
Meal meal;
meal.addItem(new ChickenBurger);
meal.addItem(new Pepsi);
return meal;
}
};
#include <QCoreApplication>
#include "MealBuilder.h"
int main() {
MealBuilder mealBuilder;
Meal vegMeal = mealBuilder.prepareVegMeal();
qDebug() << "Veg Meal";
vegMeal.showItems();
qDebug() << QStringLiteral("Total Cost: %1").arg(vegMeal.getCost());
qDebug().noquote() << "**************************************";
Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
qDebug() << "Non-Veg Meal";
nonVegMeal.showItems();
qDebug() << QStringLiteral("Total Cost: %1").arg(nonVegMeal.getCost());
}