前言
上一篇《小菜学习设计模式(二)—单例(Singleton)模式》;
其实大家都知道,在工厂方法(Factory Method)模式之前有个简单工厂模式,也就是静态工厂方法(Static Factory Method)模式,在简单工厂模式之前有个我们都熟悉的三层架构模式,那我们就上到下一层一层的来了解下。
三层架构
三层架构我们都熟悉,一开始编程的时候也是用的最多,分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL),实现了“高内聚,低耦合”的思想。
关于三层架构不需要说太多,我当时学习的时候,无意间看到李天平老师关于三层的趣味理解,觉得还蛮有意思的,很适合初学者理解,和大家分享下:
- 数据库好比猪圈,所有的猪有序地按区域或编号,存放在不同的猪栏里。
- DAL好比是屠宰场,把猪从猪圈取出来进行(处理)*,按要求取出相应的部位(字段),或者进行归类整理(统计),形成整箱的猪肉(数据集),传送给食品加工厂(BLL)。本来这里都是同一伙人既管抓猪,又管杀猪的,后来觉得效率太低了,就让一部分人出来专管抓猪了(DBUtility),根据要求来抓取指定的猪。
- BLL好比食品加工厂,将猪肉深加工成各种可以食用的食品(业务处理)。
- Web好比商场,将食品包装成漂亮的可以销售的产品,展现给顾客(UI表现层)。
- 猪肉好比Model,无论是哪个厂(层),各个环节传递的本质都是猪肉,猪肉贯穿整个过程。
- 通用类库Common,相当于工人使用的各种工具,为各个厂(层)提供诸如杀猪刀、绳子、剪刀、包装箱、工具车等共用的常用工具(类)。其实,每个部门本来是可以自己制作自己的工 具的,但是那样会使效率比较低,而且也不专业,并且很多工作都会是重复的。因此,就专门有人开了这样的工厂来制作这些工具,提供给各个工厂,有了这样的分工,工厂就可以专心做自己的事情了。
通过上面的趣味理解,脑海中应该对三层有个了解了。说到这,其实如果大家学习过MVC(模型Model-视图View-控制器Controller)的话,就发现和三层架构有点相似,都有一个表现层,但是其他两层就不同了,三层架构中没有Controller这个概念,MVC也没有把业务的逻辑访问看成两个层,这是采用三层架构或MVC搭建程序最主要的区别。当然了。在三层中也提到了Model,但是三层架构中Model的概念与MVC中Model的概念是不一样的,“三层”中典型的Model层是以实体类构成的,而MVC里,则是由业务逻辑与访问数据组成的。
简单工厂模式
静态工厂方法(Static Factory Method)模式其实不属于GOF所提出的设计模式中,我们一般在应用的时候结合三层模式下使用工厂模式使用多点,例如下面的解决方案:
上面的SeManage.IDAL就相当于抽象产品,SeManage.SQLServerDAL相当于具体产品,SeManage.DALFactory相当于工厂,决定生成何种商品的工厂。
1 /// <summary> 2 /// dal工厂 3 /// </summary> 4 public sealed class DataAccess 5 { 6 private static readonly string SQLServicePath = ConfigurationManager.AppSettings["SQLServerDAL"]; 7 public DataAccess() 8 { } 9 10 /// <summary> 11 /// 创建Changdi数据层接口。 12 /// </summary> 13 public static SeManage.IDAL.IChangdi CreateChangdi() 14 { 15 string className = SQLServicePath + ".Changdi"; 16 return (SeManage.IDAL.IChangdi)Assembly.Load(SQLServicePath).CreateInstance(className); 17 } 18 }
1 <add key="SQLServerDAL" value="SeManage.SQLServerDAL"/>
上面的代码表示根据配置文件来创建何种具体抽象类的实例(产品),下面的配置就像工厂机器的开关,决定生产哪种产品。
通过上面的代码,我们也会发现一些问题,如果产品的种类较多,工厂类里面的生产产品的方法也多,如果出现新的产品,那我们就必须在工厂类里面添加生产新产品的方法,这样就违反了高内聚责任分配原则,使代码变的不容易维护。
工厂方法(Factory Method)模式
工厂方法(Factory Method)模式是在GOF提出的设计模式中有定义的,如下:为创建对象定义一个接口,让子类决定实例化哪个类,工厂方法让一个类的实例化延迟至子类。
其实从某种方面可以说,工厂方法模式是简单工厂模式的衍生,也解决了简单工厂模式所出现的问题,例如上面所提到的。工厂方法模式其实就是把工厂抽象化了,我们可以把工厂方法模式拆分成四个元素:抽象工厂(IFactory)、具体工厂(Concrete Factory)、抽象产品(Product)和具体产品(Concrete Product)。根据这四个元素,我们可以简单的画下UML类图:
根据上面的UML类图,不难实现其代码:
1 /// <summary> 2 /// 产品接口 3 /// </summary> 4 public interface ICar 5 { 6 void Travel(); 7 } 8 9 /// <summary> 10 /// 具体产品 11 /// </summary> 12 public class Lexus : ICar 13 { 14 public void Travel() 15 { 16 Console.WriteLine("I‘m a lexus car, I‘m traveling"); 17 } 18 } 19 20 /// <summary> 21 /// 工厂接口 22 /// </summary> 23 public interface ICarFactory 24 { 25 ICar CreateCar(); 26 } 27 28 /// <summary> 29 /// 具体工厂类 30 /// </summary> 31 public class LexusFactory : ICarFactory 32 { 33 public ICar CreateCar() 34 { 35 return new Lexus(); 36 } 37 } 38 39 40 public class Client 41 { 42 private ICarFactory carFactory; 43 public Client(ICarFactory carFactory) 44 { 45 this.carFactory = carFactory; 46 } 47 48 public void doSomething() 49 { 50 ICar car = carFactory.CreateCar(); 51 car.Travel(); 52 //to do something 53 } 54 }
调用示例代码:
1 static void Main(string[] args) 2 { 3 Client client = new Client(new LexusFactory()); 4 client.doSomething(); 5 }
从上面的代码我们可以看出,工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范, 具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。其实单从这一点上,我们就会发现,和我们之前说的《小菜学习设计模式(一)—模板方法(Template)模式》中提到的模板方法模式的思想有些共同的地方,其实工厂方法(Factory Method)模式是最典型的模板方法(Template Method)模式的应用。
示例代码下载:FactoryMethod.rar
后记
插一句:上面的UML是用Edraw Mind Map这一款绘图软件画的,感觉还不错,可以画大部分的图,还在熟悉中,绿色版的哦。
下载地址:Edraw Mind Map.rar
骚年们,和小菜一起整理学习吧,未完待续。。。