为方便读者,本文已添加至索引:
在上篇笔记Builder设计模式中,时の魔导士祭出了自己的WorldCreator。尽管它因此能创造出一个有山有树有房子的世界,但是白雪公主的生活似乎并不太快乐。啊,她当然需要填饱肚子。“来点可口的意式甜点,还是独特的法式面包呢?”魔导士心想。顺便说一下,白雪公主是德国人。“那就德式烤肠怎么样?……总之,我们需要点食品加工厂~尝尝来自世界各地的美味吧!”
来自不同地域的食品加工厂各自有着独特的工艺水平,生产出来的食物口感味道上都各有千秋。但它们生产出来的都是给公主吃的食物,要怎么样去设计这个食物的供给呢?我们当然可以采用Abstract Factory(抽象工厂)模式啦!
时の魔导士合上了他心爱的魔法书。为了让白雪公主能随时随地吃上美味的食物,他在公主的城堡外建造了一个充满魔法的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);
总而言之,现在他们可以享受到美味的食物啦。
趁着白雪公主她们一行人吃饭的时间,我们来回顾一下抽象工厂的特点和实用性吧。在上面的例子中,客户即是霍比特人厨师,工厂则是FoodFactory, PizzaHut, ChineseRestaurant,产品是Dinner(Food和Drink的合集)。注意到FoodFactory仅是工厂方法的一个集合。这是最通常的实现Abstract Factory模式的方式。同时注意FoodFactory不是一个抽象类;因此它既作为AbstractFactory也作为ConcreteFactory。这是Abstract Factory模式的简单应用的另一个通常的实现。因为FoodFactory是一个完全由工厂方法组成的具体类,通过生成一个子类并重定义需要改变的操作,它很容易生成一个新的FoodFactory。我们可以看到:
当然我们可以定义一个可扩展的工厂,来解决4中所提的难处。比如给创建对象的操作增加一个参数;该参数指定了将被创建的对象的种类。不过,这是一种更灵活但不太安全的设计。
今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!