设计模式之简单工厂模式
设计模式是C#程序员从拖控件成长为技术大牛的必经之路,经过《Head First》洗礼后,作为一个随笔留在博客园吧。
OK,让我们进行第一任务:请朋友喝茶或者喝咖啡。
整理下我们的思路:喝茶或者喝咖啡,都要煮开水、洗杯子、冲泡茶(咖啡)。煮开水和洗杯子代码可以复用,考虑这个原则(实现代码的复用选择抽象类,实现多态性选择接口),我们选择创建一个抽象类,用来实现煮开水和洗杯子功能。
代码如下:
1 using System; 2 3 namespace SimpleDrinkFactory 4 { 5 abstract class BeforeDrink 6 { 7 //煮开水 8 public void BoilWater() 9 { 10 Console.WriteLine("煮开水"); 11 } 12 //洗杯子 13 public void WashCup() 14 { 15 Console.WriteLine("洗杯子"); 16 } 17 //冲泡(子类继承重写) 18 public abstract void Function(); 19 } 20 }
1 using System; 2 3 namespace SimpleDrinkFactory 4 { 5 class Tea:BeforeDrink 6 { 7 public override void Function() 8 { 9 Console.WriteLine("冲泡茶叶"); 10 //throw new NotImplementedException(); 11 } 12 } 13 }
1 using System; 2 3 namespace SimpleDrinkFactory 4 { 5 class Coffee:BeforeDrink 6 { 7 public override void Function() 8 { 9 Console.WriteLine("冲泡咖啡"); 10 //throw new NotImplementedException(); 11 } 12 } 13 }
1 using System; 2 3 namespace SimpleDrinkFactory 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Console.WriteLine("星期天,朋友来我家玩,我请大家和饮料。"); 10 Console.WriteLine("请选择要喝的饮料:Tea or Coffee"); 11 string type = Console.ReadLine(); 12 BeforeDrink drink = null; 13 switch (type) 14 { 15 case"Tea": 16 drink=new Tea(); 17 break; 18 case "Coffee": 19 drink = new Coffee(); 20 break; 21 default: 22 Console.WriteLine("Sorry,没有您选择的饮料"); 23 break; 24 } 25 drink.BoilWater(); 26 drink.WashCup(); 27 drink.Function(); 28 Console.WriteLine("朋友喝"+ type +""); 29 Console.WriteLine("朋友满意的走了"); 30 Console.ReadKey(); 31 } 32 } 33 }
执行之后应该是下图所示
过了一段时间,岳父来我家做客,点名只喝温酒。
岳父发话了,咋办,赶紧按照下面流程重新修改咱们的Drink程序呗:
1、添加alcohol类,继承于BeforeDrink,重写Function方法
2、修改Main()中的Switch方法,添加alcohol分支
OK,经过修改,岳父可以喝温酒了。但是岳母来了,点名要喝红糖水;父亲来了,点名要喝。。。
然后大家就会发现,维护起来太麻烦了,同时我们的Switch也会越来也多分支。
这个时候,终于要用到我们的工厂模式了。
看下简单工厂模式的UML图(UML不会用,见谅)
按照上述UML图写我们的代码。
Tea、Coffee、BeforeDrink类和上面一样没有变化,新增SimpleDrinkFactory类和修改Main();
1 namespace SimpleDrinkFactory 2 { 3 class SimpleDrinkFactory 4 { 5 public static BeforeDrink CreatDrink(string type) 6 { 7 BeforeDrink drink = null; 8 if (type.Equals("Tea")) 9 { 10 drink = new Tea(); 11 } 12 else if (type.Equals("Coffee")) 13 { 14 drink = new Coffee(); 15 } 16 return drink; 17 } 18 } 19 }
1 using System; 2 3 namespace SimpleDrinkFactory 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 Console.WriteLine("星期天,朋友来我家玩,我请大家和饮料。"); 10 Console.WriteLine("请输入要喝的饮料:"); 11 string type = Console.ReadLine(); 12 BeforeDrink sdf = SimpleDrinkFactory.CreatDrink(type); 13 sdf.BoilWater(); 14 sdf.WashCup(); 15 sdf.Function(); 16 //switch (type) 17 //{ 18 // case"Tea": 19 // drink=new Tea(); 20 // break; 21 // case "Coffee": 22 // drink = new Coffee(); 23 // break; 24 // default: 25 // Console.WriteLine("Sorry,没有您选择的饮料"); 26 // break; 27 //} 28 //drink.BoilWater(); 29 //drink.WashCup(); 30 //drink.Function(); 31 Console.WriteLine("朋友喝"+ type +""); 32 Console.WriteLine("朋友满意的走了"); 33 Console.ReadKey(); 34 } 35 } 36 }
执行之后的结果如下
从代码上看,其实变化的部分只是将Main()中的代码Copy至新增的SimpleDrinkFactory类中。
但这恰恰是面向对象设计的一个很关键的思路。(还记得封装、继承、多态么)
在以后的日记里,咱们会遇到更简单的方法,可以让我们的代码自动创建不同的实例,不用每次新增一个饮料,都要重新修改Switch或者if语句。
Ps:古语道,世界上最难的唯有两件事,一为将别人的钱财装进自己的口袋里,二为将自己的思想塞入别人的脑袋中。古人诚不欺我。