这是我们用得比较多的一种设计模式,也是23种标准设计模式之一,使用前面讲的简单工厂设计模式,遇到具体产品经常变换时就不太适合了,违反了开闭设计原则;怎么才能避免修改工厂类呢?工厂方法模式可以做到。
工厂方法模式要求我们应该有一个抽象的工厂类,我们知道尽量使用抽象类或接口来定义就可以达到一个开闭原则的效果,这样我们在抽象的工厂类定义一个生产产品的方法,这个方法就是工厂方法,这也是工厂方法模式的由来,他具体的行为会有他的子类或实现类来实现。如果想生产某种产品,就定义一个新的产品,新的产品工厂类,这样就实现了不同的产品进行一个不同的创建,这样如果有信的产品,只需要添加新的工厂类,原来写好的代码不会发生变化,这种方式符合开闭原则,可扩展比较好。
添加一个具体产品,只需要在添加一个具体产品的工厂类实现抽象工厂类,不需要修改原来的代码
示例代码:
抽象产品类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /* 10 动物抽象类 11 * 抽象产品 12 */ 13 public abstract class Animal 14 { 15 public abstract void Eat(); 16 } 17 }
抽象工厂类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /* 10 动物抽象工厂类 11 12 */ 13 public abstract class AnimalFactory 14 { 15 public abstract Animal GetAnimal(); 16 17 } 18 }
生产狗的具体工厂类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 具体工厂:生成狗 11 /// </summary> 12 public class DogFactory :AnimalFactory 13 { 14 15 public override Animal GetAnimal() 16 { 17 return new Dog(); 18 } 19 } 20 }
生产企鹅的具体工厂类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 具体工厂:生成企鹅 11 /// </summary> 12 public class PenguinFactory :AnimalFactory 13 { 14 public override Animal GetAnimal() 15 { 16 return new Penguin(); 17 } 18 } 19 }
View Code
具体产品狗类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /* 10 具体的产品类,实现抽象产品类 11 */ 12 public class Dog:Animal 13 { 14 // 实现抽象方法 15 public override void Eat() 16 { 17 Console.WriteLine("狗在吃饭!"); 18 } 19 } 20 }
View Code
具体产品企鹅类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /* 10 具体产品类,实现抽象产品类 11 12 */ 13 public class Penguin : Animal 14 { 15 // 实现抽象方法 16 public override void Eat() 17 { 18 Console.WriteLine("企鹅在吃饭!"); 19 } 20 } 21 }
View Code
客户端调用:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 AnimalEat(new DogFactory()); 14 Console.ReadKey(); 15 } 16 17 static void AnimalEat(AnimalFactory af) 18 { 19 Animal am = af.GetAnimal(); 20 am.Eat(); 21 } 22 } 23 }
View Code
类图:
如果想在增加一个Cat类,只需要增加一个具体的Cat类实现Animal类的方法,增加一个具体的Cat工厂类实现抽象工厂类即可,不需要在修改已经写好的代码,符合开闭原则。
使用接口的方式实现工厂模式
需求:使用面向对象的方式设计一个系统,描述使用卡车从事货运,使用公共汽车从事客运。使用工厂模式实现。
1、汽车接口:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 汽车接口 11 /// </summary> 12 public interface ICar 13 { 14 /// <summary> 15 /// 描述汽车从事的活动 16 /// </summary> 17 void Work(); 18 } 19 }
2、分别定义卡车(Truck)和公共汽车(Bus)类实现汽车接口(ICar)里面的Work()方法
Truck类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 卡车类 11 /// </summary> 12 public class Truck : ICar 13 { 14 /// <summary> 15 /// 卡车从事的活动 16 /// </summary> 17 public void Work() 18 { 19 Console.WriteLine("卡车从事货运"); 20 } 21 } 22 }
Bus类:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 公共汽车类 11 /// </summary> 12 public class Bus:ICar 13 { 14 /// <summary> 15 /// 公共汽车从事的活动 16 /// </summary> 17 public void Work() 18 { 19 Console.WriteLine("公共汽车从事客运"); 20 } 21 } 22 }
3、定义汽车的工厂接口(ICarFactory):
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 汽车工厂接口 11 /// </summary> 12 public interface ICarFactory 13 { 14 ICar GetCar(); 15 } 16 }
4、分别定义卡车工厂(TruckFactory)和公共汽车工厂(BusFactory)实现ICarFactory接口
TruckFactory工厂:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 卡车工厂接口 11 /// </summary> 12 public class TruckFactory:ICarFactory 13 { 14 /// <summary> 15 /// 返回卡车类 16 /// </summary> 17 /// <returns></returns> 18 public ICar GetCar() 19 { 20 return new Truck(); 21 } 22 } 23 }
BusFactory工厂:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 /// <summary> 10 /// 公共汽车工厂 11 /// </summary> 12 public class BusFactory:ICarFactory 13 { 14 /// <summary> 15 /// 返回公共汽车类 16 /// </summary> 17 /// <returns></returns> 18 public ICar GetCar() 19 { 20 return new Bus(); 21 } 22 } 23 }
5、主程序调用:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 工厂模式 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 14 CarWork(new TruckFactory()); 15 Console.ReadKey(); 16 } 17 18 19 /// <summary> 20 /// 根据汽车工厂返回具体的汽车类 21 /// </summary> 22 /// <param name="cf"></param> 23 static void CarWork(ICarFactory cf) 24 { 25 ICar c = cf.GetCar(); 26 c.Work(); 27 } 28 } 29 }
6、程序运行结果
代码连接地址:http://files.cnblogs.com/files/dotnet261010/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.rar