设计模式一 —— 工厂模式
设计模式一 —— 工厂模式
工厂类型解决的是怎么new()的问题,它告诉我们可以通过增加新的对象专门管理“变化”。例如,我们为了解决new()引起的变化,我们就引入工厂类型,由新的工厂类型专门处理new()相关的“变化”,确保客户程序不受这些变化的直接影响。
一、简单工厂类
简单工厂类是工厂方法和抽象工厂的“预备工作”
1、简单工厂的特性/工厂类型和直接new()的不同
1、对加工的类型做抽象(IProduct);
2、定义专门负责构造的类型Factory;
3、通过IProduct隔离了客户端与具体类型ooxxInfo的依赖关系,ooxxInfo的CDRU无碍大局。
2、简单工厂类型的弊端
1、当ooxxInfo变化时,Factory类型也要反复编译,如果没有其他控制,客户程序也要"陪同"编译;
2、如果构造一个Factory实例,并只使用一次就不再使用,浪费资源,尤其是该过程频繁使用;
3、解决方案
1、把工厂设计为单件(Singleton)方式,因为工厂的职责相对单一,所有客户程序共享唯一的一个Factory类型实例;
2、使用静态类/静态工厂模式(比较简单不做介绍)。但是静态类不能被继承。
如果应用中需要的工厂类型非常多,而各个工厂类型职责又雷同,这时就需要进一步抽象。
二、静态工厂模式
简单工厂加上static关键字,值得注意的是静态类不能被继承,也就是说将工厂模式某一类比作俄罗斯套娃的话,就到此结束了,不能再套下一个阶段了。
三、工厂方法模式
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
作为简单工厂的一个扩展,工厂方法模式的意图就是把类的实例化过程延迟到子类,将new()的工作交给工厂完成,同时对工厂自身进行抽象,然后客户程序基于工厂的抽象行为构造所需的类型实例。
提供一个用于创建对象的接口(工厂接口),让其实现类(工厂实现类)决定实例化哪一类(产品类),并且由该类实现类创建对应类的实例。
1、工厂方法主要的4个角色
抽象产品类型(IProduct):对待构造类型抽象后的接口;
具体产品类型(ooxxInfo):具体待构造类型,需要由工厂延迟实例化;
工厂类型的抽象接口(IFactory)
具体工厂类型(ooxxFactory)
2、工厂方法模式适用场景
1、客户程序需要隔离自己与待new()类型间的耦合关系;
2、开发阶段客户程序还无法明确预知需要new()的具体类型;
3、客户程序将new()的工作交给外部对象完成;
4、各种需要new()的对象虽然可以统一抽象为某个接口,但他们的继承关系太过繁琐,层次也比较复杂;
四、抽象工厂模式
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类型
五、抽象工厂和工厂方法区别
抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中,通常一个产品结构,表现为一个接口或者抽象类,也就是说,工厂方法模式提供的所有产品都是衍生自同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。
如果工厂的产品全部属于同一个等级结构,则属于工厂方法模式;如果工厂的产品来自多个等级结构,则属于抽象工厂模式。
所以抽象工厂模式相对而言可扩展性更好。
六、优化
对于实现工厂模式之后,需要解耦工厂类型与客户程序,采用“依赖注入”方法。
对于一些配置文件也能解决解耦问题。
在实际项目中经常需要加工一批对象,如果按部就班的采用一件接一件的模式来生成,效率很低,最好专门设计独立的批量工厂。其实“工厂”这个名词体现的也是这个意思。
七、小结
新的工厂类型不仅可以完成经典工厂方法模式所希望实现的各项要求,同时它可以作为整个项目一个独立的唯一的入口,供项目中各个子系统的访问和使用。原因在于他的底层将工厂接口与抽象产品类型的依赖关系变成基于CLR“万能工厂”类型的构造过程。后续,具体项目中可能还要进一步修改这个工厂类型,提供更多的重载方法。
工厂方法模式重新诠释了如何去new()的问题,通过引入新的对象,在很大程度上解放了客户程序对具体类型的依赖,其方法就是延迟构造到子类,但依赖关系始终存在,解放一个对象的时候等于把麻烦转嫁到另一个对象身上。为此,项目中往往最后把推不掉的依赖关系推到配置文件或“万能工厂”上,这样经典的工厂方法模式往往在项目中被演绎成“ 工厂方法 + 依赖注入 + 配置文件访问 ”的组合方式。
在日常项目中,我们要防止工厂模式的滥用。