工厂模式
先来说说现实生活中的工厂。有一个汽车零售商老板,向宝马公司预定了10张宝马,并签订合同,宝马公司前台将这个订单发送给生产宝马汽车的工厂,工厂收到这个订单后开始生产,等生产结束再把车辆交给零售商老板,完成了这个订单。在这过程中,零售商老板只告诉宝马公司他需要的车型,他并不知道这车是通过怎样的方式生产出来的。所谓工厂模式就是创建对象的一种模式,是我们最常用的实例化对象的模式。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给程序带来更大的可扩展性和尽量少的修改量。
工厂模式有三种分类:简单工厂,工厂方法,抽象工厂。我通过生产汽车来举例。其中有三个类,分别是Car类(轿车类),Bus类(公交车类),Truck类(卡车类),这三个类代表“工厂”可以生产的“产品”。
class Car // 轿车类 { public Car() { Console.WriteLine("生产了一辆轿车!"); } } class Bus // 公交车类 { public Bus() { Console.WriteLine("生产了一辆公交车!"); } }
class Truck // 卡车类 { public Truck() { Console.WriteLine("生产了一辆卡车!"); } }
先看看简单工厂模式。
/// <summary> /// 简单工厂模式 /// </summary> namespace ConsoleApp1 // 命名空间 { /// <summary> ///可以在工厂里制造的车型 /// </summary> public enum Cartype { car, bus, truck } /// <summary> ///这是一个类,模拟客户 /// </summary> class Program { static void Main(string[] args) { //客户需要让工厂生产一张轿车 object obj = Factory.Create(Cartype.car); // 客户将参数传递给工厂,让工厂开始生产车辆 Console.WriteLine(obj.GetType()); // 检测车类型 Console.ReadLine(); } } /// <summary> /// 制造车辆的工厂 /// </summary> public static class Factory { public static object Create(Cartype cartype) // 通过枚举类型的参数动态创建对象 { switch (cartype) { case Cartype.car: return new Car(); break; case Cartype.bus: return new Bus(); break; case Cartype.truck: return new Truck(); break; default: return null; break; } } }
说明:以上有2个类,一个是客户类(Program类),包含程序入口main方法,另一个是工厂类(Factory类),通过客户传递的参数进行实例化对象,然后再将“生产”出来的对象return给客户。
运行结果:
优点:工厂类包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类。对于客户端来说,去除了对具体产品的依赖。
缺点:不符合开放封闭原则(OCP)。不修改代码的话,是无法进行拓展的(如果增加新的产品,需要增加switch分支)。
接下来简要说说工厂方法,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法将类的实例化延长到子类。在工厂方法中,工厂的接口中只包含一个方法。在此不再展示实现源码。
来看看这种模式的优点和缺点:
优点:符合开放封闭原则(OCP),工厂方法模式实现时,客户端需要决定实例化哪个工厂来创建对象。工厂方法把简单工厂的内部创建对象的逻辑判断移到了客户端。如果需要修改,只需要修改客户端即可!
缺点:但随着产品类的增加,对应的工厂类也会随之增多。
抽象工厂,是应对产品族概念的,比如说,每个汽车公司可能要同时生产轿车,公交车,卡车,那么每一个工厂都要有创建轿车,公交车和卡车的方法。
/// <summary> /// 抽象工厂 /// </summary> namespace ConsoleApp2 { /// <summary> /// 客户 /// </summary> class Program { static void Main(string[] args) { Factory_A factory_A = new Factory_A(); // 创建Factory_A(宝马公司)实例 Factory_B factory_B = new Factory_B(); // 创建Factory_B(奔驰公司)实例 //在宝马公司生产车辆 object obj1 = factory_B.CreateBus(); // 在宝马公司生产公交车 Console.WriteLine(obj1.GetType()); // 检测是否是公交车 object obj2 = factory_B.CreateCar(); // 在宝马公司生产轿车 Console.WriteLine(obj2.GetType()); // 检测是否是轿车 object obj3 = factory_B.CraeteTruck(); //在宝马公司生产卡车 Console.WriteLine(obj3.GetType()); // 检测是否是卡车 // 在奔驰公司生产车辆 object obj4= factory_A.CraeteTruck(); // 在奔驰公司生产卡车 Console.WriteLine(obj4.GetType()); // 检测是否是卡车 object obj5 = factory_A.CreateBus(); // 在奔驰公司生产公交车 Console.WriteLine(obj5.GetType()); // 检测是否是公交车 object obj6 = factory_A.CreateCar(); // 在奔驰公司生产轿车 Console.WriteLine(obj6 .GetType()); // 检测是否是轿车 Console.ReadLine(); } } /// <summary> /// 接口 工厂可以制造的产品 /// </summary> interface FactoryMethod { object CreateBus(); // 制造公交车 object CreateCar(); // 制造轿车 object CraeteTruck(); // 制造卡车 } /// <summary> /// 宝马公司,继承了FactoryMethod,所以可以制造3种车 /// </summary> public class Factory_A : FactoryMethod { public object CraeteTruck() { return new Truck(); } public object CreateBus() { return new Bus(); } public object CreateCar() { return new Car (); } } /// <summary> ///奔驰公司,继承了FactoryMethod,所以可以制造3种车 /// </summary> public class Factory_B : FactoryMethod { public object CraeteTruck() { return new Truck(); } public object CreateBus() { return new Bus(); } public object CreateCar() { return new Car(); } }
运行结果:
工厂模式总结:
简单工厂:简单实用,但违反开放封闭。
工厂方法:开放封闭,单一产品。
抽象工厂:开放封闭,多个产品。