来自不同地域的食品加工厂各自有着独特的工艺水平,生产出来的食物口感味道上都各有千秋。但它们生产出来的都是给公主吃的食物,要怎么样去设计这个食物的供给呢?我们当然可以采用Abstract Factory(抽象工厂)模式啦!
要点梳理
目的分类
对象创建型模式
主要功能
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
适用情况
一个
系统要独立于它的产品的创建、组合和表示时
一个系统要由多个产品系列中的一个来配置时
当我们要强调一系列相关的产品对象的设计以便进行联合使用时
当我们提供一个产品类库,而只想显示它们的接口而不是实现时
参与部分
AbstractFactory:声明一个创建抽象产品对象的操作接口
ConcreteFactory:实现创建具体产品对象的操作
AbstractProduct:为一类产品对象声明一个接口
ConcreteProduct:定义一个将被相应的具体工厂创建的产品对象;实现AbstractProduct接口
Client:仅使用由AbstractFactory和AbstractProduct类声明的接口
协作过程
通常在运行时刻创建一个ConcreteFactory类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂
AbstractFactory将产品对象的创建延迟到它的ConcreteFactory
示例分析 - 美味的食品工厂
时の魔导士合上了他心爱的魔法书。为了让白雪公主能随时随地吃上美味的食物,他在公主的城堡外建造了一个充满魔法的FoodFactory(魔法总是虚幻的,可以认为它只是一个Abstract Factory),它能创造食物Food和饮料Drink,请看示例:
复制代码
1 class FoodFactory {
2 public:
3 FoodFactory();
4
5 virtual Dinner* makeDinner() const { return new Dinner(); }
6 virtual Food* makeFood(int f) const { return new Food(f); }
7 virtual Drink* makeDrink(int d) const { return new Drink(d); }
8 }
复制代码
他当然还教会7个霍比特人中的一个生产食物的咒语(createFood),以使得他荣幸地成为白雪公主的第一任美味厨师长。createFood方法以FoodFactory为参数,这样小霍比特人就能指定要制作的食物和饮料了:
复制代码
1 Dinner* Hobbit::createFood (FoodFactory& factory) {
2 Dinner* dinner = factory.makeDinnner();
3 Food* food = factory.makeFood(9);
4 Drink* drink = factory.makeDrink(9);
5
6 dinner->addFoodAndDrink(food, drink);
7
8 return dinner;
9 }
复制代码
等等,怎么是9份?啊,白雪公主要吃霍比特人2倍的量哦。另外,时の魔导士悄悄地告诉小霍比特人,其实FoodFactory只是一个统一的魔法平台而已,想要让白雪公主尝到世界各地的美味,他还需要建造相应的具体工厂,比如说“PizzaHut”:
复制代码
1 class PizzaHut : public FoodFactory {
2 public:
3 PizzaHut();
4
5 virtual Food* makeFood(int f) const { return new Pizza(f, addCheese()); }
6 virtual Drink* makeDrink(int d) const { return new Coffee(d); }
7 protected:
8 Cheese* addCheese() const;
9 }
复制代码
嗯……更多芝士,更多美味~~“当然,你甚至可以来点中餐!”时の魔导士兴奋地说道:
复制代码
class ChineseRestaurant : public FoodFactory {
public:
ChineseRestaurant();
virtual Food* makeFood(int f) const { return new ChineseFood(f, "Egg Fried Rice"); }
virtual Drink* makeDrink(int d) const { return new Maotai(d, 52); }
}
复制代码
现在,我们可以看到Abstract Factory的好处了,如果白雪公主想吃意式菜:
1 Hobbit theCook;
2 PizzaHut factory;
3 Dinner* dinner = theCook.createFood(factory);
那如果她突然想吃中餐,要做的仅仅是:
1 Hobbit theCook;
2 ChineseRestaurant factory;
3 Dinner* dinner = theCook.createFood(factory);
总而言之,现在他们可以享受到美味的食物啦。