千百年来,关于“空中花园”有一个美丽动人的传说。新巴比伦国王尼布甲尼撒二世娶了米底的公主安美依迪丝为王后。公主美丽可人,深得国王的宠爱。可是时间一长,公主愁容渐生。尼布甲尼撒不知何故。公主说:“我的家乡山峦叠翠,花草丛生。而这里是一望无际的巴比伦平原,连个小山丘都找不到,我多么渴望能再见到我们家乡的山岭和盘山小道啊!”原来公主得了思乡病。于是,尼布甲尼撒二世令工匠按照米底山区的景色,在他的宫殿里,建造了层层叠叠的阶梯型花园,上面栽满了奇花异草,并在园中开辟了幽静的山间小道,小道旁是潺潺流水。工匠们还在花园中央修建了一座城楼,矗立在空中,巧夺天工的园林景色终于博得公主的欢心。故事讲到这里,在我们的故事中蕴藏着怎样的设计模式呢?今天这篇博文的内容就从我们美丽动人的传说空中花园开始!
如果空中花园中只种花,那么就用简单工厂就可以了,如果公主喜欢各种各样的花,种类比较繁多,我们就需要用工厂方法,把公共有的东西抽象出来,再者如果公主想要扩大花园的规模,一个在安徽一个在河北,这样工厂方法也就无法实现了,这个时候,就需要用到抽象工厂,把各种各样的植物,又组成一个空中花园。我们先来看一下工厂方法模式模式的结构图:
在前面的博文中,我们学习过简单工厂模式,简单工厂是一个工厂只生产一类的产品,面对的是具体的类,工厂方法是可以生产不同的产品,把公共的方法抽象出来,然后进行创建各种各样的产品.抽象工厂把几种产品划出共同的东西,把相互依赖的对象抽象出来,只要实现这些接口就可以得到不同的产品,简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,下面就具体看看工厂模式是如何解决该问题的。 工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创建推迟到子类中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口,这样工厂方法模式就可以允许系统不修改工厂类逻辑的情况下来添加新产品,这样也就克服了简单工厂模式中缺点。下面看下工厂模式的具体实现代码(这里还是以简单工厂模式中点菜的例子来实现:
<span style="font-size:18px;">namespace 设计模式之工厂方法模式 { /// <summary> /// 菜抽象类 /// <summary> public abstract class Food { // 输出顾客点了什么菜 public abstract void Print(); } /// 酸辣土豆丝这道菜 public class ChiliSourPotatod: Food { public override void Print() { Console.WriteLine("酸辣土豆丝出锅!"); } } /// <summary> /// 姜汁皮蛋这道菜 /// </summary> public class PreservedEggSinGingerSauce : Food { public override void Print() { Console.WriteLine("姜汁皮蛋"); } } /// <summary> /// 抽象工厂类 /// </summary> public abstract class Creator { // 工厂方法 public abstract Food CreateFoddFactory(); } /// <summary> /// 酸辣土豆丝工厂类 /// </summary> public class ChiliSourPotatod:Creator { /// <summary> /// 负责创建酸辣土豆丝这道菜 /// </summary> /// <returns></returns> public override Food CreateFoddFactory() { return new ChiliSourPotatod(); } } /// <summary> /// 姜汁皮蛋工厂类 /// </summary> public class PreservedEggSinGingerSauceFactory:Creator { /// <summary> /// 负责创建姜汁皮蛋这道菜 /// </summary> /// <returns></returns> public override Food CreateFoddFactory() { return newPreservedEggSinGingerSauce(); } } /// <summary> /// 客户端调用 /// </summary> class Client { static void Main(string[] args) { // 初始化做菜的两个工厂() Creator ChiliSourPotatodFactory = new ChiliSourPotatodFactory(); Creator PreservedEggSinGingerSauceFactory = new PreservedEggSinGingerSauceFactory(); // 开始做酸辣土豆丝 Food ChiliSourPotatod = tomatoScrambledEggsFactory.CreateFoddFactory(); ChiliSourPotatod.Print(); //开始做姜汁皮蛋 FoodPreservedEggSinGingerSauce =PreservedEggSinGingerSauceFactory.CreateFoddFactory(); PreservedEggSinGingerSauce.Print(); Console.Read(); } } } </span>
使用工厂方法实现的系统,如果系统需要添加新产品时,我们可以利用多态性来完成系统的扩展,对于抽象工厂类和具体工厂中的代码都不需要做任何改动。例如,我们我们还想点一个“黄瓜炒鸡蛋”,此时我们只需要定义一个黄瓜炒鸡蛋具体工厂类和黄瓜炒鸡蛋类就可以。而不用像简单工厂模式中那样去修改工厂类中的实现,具体代码如下所示:
<span style="font-size:18px;">/// <summary> /// 黄瓜炒鸡蛋这道菜 /// </summary> public class ScrambleEggWithCucumber : Food { /// <summary> /// 重写抽象类中的方法 /// </summary> public override void Print() { Console.WriteLine("黄瓜炒鸡蛋好了"); } } /// <summary> /// 黄瓜炒鸡蛋工厂类,负责创建黄瓜炒鸡蛋这道菜 /// </summary> public classScrambleEggWithCucumberFactory : Creator { /// <summary> /// 负责创建黄瓜炒鸡蛋这道菜 /// </summary> /// <returns></returns> public override Food CreateFoddFactory() { return new ScrambleEggWithCucumber(); } } /// <summary> /// 客户端调用 /// </summary> class Client { static void Main(string[] args) { // 如果客户又想点黄瓜炒鸡蛋了 // 再另外初始化一个黄瓜炒鸡蛋工厂 Creator ScrambleEggWithCucumberFactor = new ScrambleEggWithCucumberFactory(); // 利用黄瓜炒鸡蛋工厂来创建黄瓜炒鸡蛋这道菜 Food ScrambleEggWithCucumber = ScrambleEggWithCucumberFactor.CreateFoddFactory(); ScrambleEggWithCucumber.Print(); Console.Read(); } } </span>
简单工厂:严格说并不是一个设计模式。简单工厂没有抽象类,只有一个具体工厂类如MyFactory,然后MyFactory里面有个工厂方法CreateProduct返回一个基类产品,具体返回什么具体实例通过传入参数然后用case判断。用手机生产做个例子:比如魅族简单工厂就是只有MeizuFactory工厂类,工厂方法就是CreateMeizuPhone,参数是Meizu手机型号,根据不同型号创建不同的Meizu手机(使用case)。很明显的缺点就是Meizu每发明一个新型号的手机都需要修改简单工厂类(增加case判断),违反了封闭修改,开放扩展原则。
工厂方法:该模式有一个抽象基类和若干个派生的具体工厂类,基类定义了一个虚工厂方法返回指定产品类的基类,派生类需要实现该虚方法并创建具体产品类返回。注意工厂方法的每个具体工厂只负责返回一种产品类。同样以手机生产做例子:Meizu工厂方法模式有一个工厂基类MeizuFactory,注意此工厂和上面不一样,是抽象的。该类定义一个虚工厂方法CreateMeizuPhone,该方法返回MeizuPhone基类。然后不同型号的手机对应一个该型号的手机工厂,这样的优点就是,新出一个Meizu手机型号,只需派生一个该型号的工厂而无需修改原来的代码。符合封闭修改,开放扩展原则。设计之旅,未完待续......