简单工厂模式
简单工厂模式不是一个标准的设计模式,但是它实在是太常用了,简单而又神奇,所以需要好好掌握它。
接口回顾:
(概念)大家都知道,在java开发中,要“面向接口编程”。所谓接口是一种特殊的抽象类,跟一般抽象类相比,接口里面所有方法都是抽象方法,所有属性都是常量。即接口里面只有方法定义而没有任何方法实现。
(用途)用接口来定义实现类的外观,也就是实现类的行为定义,用来约束实现类的行为。接口相当于一份契约,根据外部需要的功能,约定了实现类应该要实现的功能,但是具体实现类除了实现接口约定的功能外,还可以根据需要实现其他一些功能,这是允许的,也就是说实现类的功能包含但不仅限于接口约束的功能。
(思想)接口的思想就是“封装隔离”。通常提到的封装是指数据的封装,但是这里的封装是指“对被隔离体的行为的封装”或“对被隔离体的职责的封装”;而隔离指的是外部调用和内部实现,外部调用只能通过接口进行调用,外部调用是不知道内部具体实现的,也就是说外部调用和内部实现是被接口隔离开的。
(好处)由于外部调用和内部实现是被接口隔离开了,那么只要接口不变,内部实现的变化就不会影响到外部应用,从而使得系统更灵活,具有更好的可扩展性和可维护性,这也就是所谓“接口是系统可插拔性的保证”这句话的意思。
(选择)既然接口是一种特殊的抽象类,那么在开发中该如何选择接口和抽象类呢?对于它们的选择,在开发中是一个很重要的问题,特别总结两句给大家:
1.优先选用接口。
2.在既要定义子类的行为,又要为子类提供公共的功能时应选择抽象类。
面向接口编程:
在java程序设计里面,非常讲究层的划分和模块的划分。通常按照三层来划分java程序,分别是表现层、逻辑层、数据层,它们之间都要通过接口来通信。
在每一个层里面,又有很多个小模块,每个小模块对外则是一个整体,所以模块对外应该提供接口,其他地方需要使用到这个模块功能时,可以通过此接口来进行调用。这也就常说的“接口是被其隔离部分的外观”。基本的三层结构如下图所示。
在一个层内部的各个模块间的交互要通过接口,如下图所示。
上面频频提到“组件”,那么什么是组件呢?
所谓组件:从设计上讲,组件就是能完成一定功能的封装体。小到一个类,大到一个系统,都可以成为组件,因为一个小系统放到更大的系统里面去,也就当个组件而已。事实上,从设计的角度看,系统、子系统、模块、组件等说的其实是同一回事,都是完成一定功能的封装体,只不过功能多少不同而已。
继续刚才的思路,大家会发现,不管是一层还是一个模块或者一个组件,都是一个被接口隔离的整体,我们可以统一认为它们都是接口隔离体即可,如下图所示:
简单工厂的结构和说明:
需要注意工厂类的位置,它是位于封装体内部,所以工厂类是可以知道具体实现类的。就好比一个组件,接口、实现类、工厂类是位于组件内部,只有接口和工厂是对外的,而具体实现类是不对外的。
简单工厂的结构如下图所示。
示例代码:
public interface Api { public void operation(string s); } public class ImplA implements Api { public void operation(string s) { System.out.println(s); } } //类名称建议为“模块名+Factory” //因为简单工厂创建对象的范围建议控制在一个组件级别或一个模块级别,不要太大 public class Factory { //方法名建议为“create+接口名称” //通常没必要创建工厂类实例,一般当一个工具类,所以工厂方法一般是静态方法 //一个工厂类里像这样的工厂方法可以有很多,可以创建接口、抽象类或类实例 //简单工厂方法内部主要实现的功能是“选择合适的实现类” //既然要实现选择,那么需要选择的条件或选择的参数,它们的来源可有以下几种 Public static Api createApi() { //来源于客户端,由client来传入参数 //来源于配置文件,从配置文件获取,后利用反射,也可以利用Ioc/DI //来源于程序运行期间某个值,比如从缓存中获取某个运行期的值 } } public class Client { public static void main(string[] args) { //通过简单工厂来获取接口对象 Api api = Factory.createApi(); api.operation(“正在使用简单工厂”); } }
简单工厂的本质:
本质是“选择实现”,实现是已经做好的了。就算实现再简单,也不是在工厂里面来实现。简单工厂的目的在于为客户端来选择相应的实现,从而使客户端和实现之间解耦。这样一来具体实现发生了变化,就不会变动客户端了,这个变化会被简单工厂吸收和屏蔽掉。
建议在以下情况中选择简单工厂:
1.如果想要完全封装具体实现,让外部只能通过接口来操作封装体。
2.如果想要把对外创建对象的职责集中管理和控制,一个简单工厂可以创建很多的、不相干的对象,可以把对外创建对象的职责集中到一个简单工厂,从而实现集中管理和控制。