这篇博文介绍简单工厂模式,设计模式并不是固定的二十三种,不同的书介绍的可能有出入,这篇介绍的简单工厂模式在有些书上就忽略不介绍了。设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。从设计模式上的定义可以了解到设计模式的本质,既然是总结出来的,肯定有出入。作为学习设计模式来说,还是把这个也记录下来,能给跟多一些思考。
简单工厂模式是工厂模式的简化版,正因为如此,所以他的使用可以说是非常的普遍,很多代码中都有他的影子。接下来我们剖析简单工厂模式。
不用模式场景
java 是面向对象语言,是面向接口编程。接下来就先来看一个例子。
1 /****************** 接口 ****************************/ 2 public interface iTest { 3 4 void funTest(String strTest); 5 6 } 7 8 /****************** 类 实现上面接口 ********************/ 9 10 public class CTest implements iTest { 11 12 @Override 13 public void funTest(String strTest) { 14 // TODO Auto-generated method stub 15 System.out.println(strTest); 16 } 17 18 } 19 20 /****************** 调用 ********************/ 22 public class Client { 23 24 public static void main(String[] args) { 25 // TODO Auto-generated method stub 26 iTest it = new CTest(); 27 it.funTest("I am CTest class!"); 28 } 29 }
当初我们学习 java 的时候就是这样来实现的,这个在练习和学习里面是没有问题,甚至在不分模块的简单系统里面也是问题不大的。但是想这样一个问题,如果客户端调用的是一个模块,那么我们不仅需要知道这个模块的接口,还需要知道实现那些类,而一个模块里面用到的类是非常多的。这样调用起来非常麻烦,而且还暴露了模块的内部实现逻辑,没有做好模块的内部封装。这样一思考问题就显而易见了。
简单工厂演化
根据模块的封装性,把上面的实现调整一下。
1 /** 2 * 引入工厂类 3 * @author Administrator 4 */ 5 public class StaticFactory { 6 //这里是 static 方法 7 public static iTest createAPI(){ 8 iTest it = new CTest(); 9 return it; 10 } 11 }
引入简单工厂,这个工厂用来创建具体实现,返回的是接口类型。那么再看下客户端调用有什么变化
public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //iTest it = new CTest(); //it.funTest("I am CTest class!"); /******简单工厂方法的调用*****/ iTest its = StaticFactory.createAPI(); its.funTest("i am created class by StaticFactoy!"); } }
这儿可以看出来客户端调用已经不用知道具体实现的类型了,具体实现类型已经放入了引入的工厂类来显示了,虽然只是一个小小的变动,但是如果放入了实际的场景中,就有质的变化。
实际运用中的简单工厂模式,当然不是这么简单了,应该有更多的逻辑,这里稍微扩展一下,一个接口一般是实现不同的类,那么可以根据不同的类型来选择不同的实现的类。
1 /** 2 * 引入工厂类 3 * @author Administrator 4 */ 5 public class StaticFactory { 6 /** 7 * 参数注释1 8 */ 9 public static final String Type1 = "1"; 10 /** 11 * 参数注释2 12 */ 13 public static final String Type2 = "2"; 14 //这里是 static 方法 15 public static iTest createAPI(String Type){ 16 iTest it =null; 17 if(Type.equals(Type1)){ 18 it = new CTest(); 19 } 20 else if(Type.equals(Type2)){ 21 it = new Ctest2(); 22 } 23 return it; 24 } 25 } 26 27 /************ 客户端调用 ****************/ 28 29 public class Client { 30 public static void main(String[] args) { 31 // TODO Auto-generated method stub 32 //iTest it = new CTest(); 33 //it.funTest("I am CTest class!"); 34 35 /******简单工厂方法的调用*****/ 36 //iTest its = StaticFactory.createAPI(); 37 //its.funTest("i am created class by StaticFactoy!"); 38 39 /******改善简单工厂方法的调用*****/ 40 iTest its = StaticFactory.createAPI(StaticFactory.Type1); 41 its.funTest("我是第一个接口实现"); 42 its = StaticFactory.createAPI(StaticFactory.Type2); 43 its.funTest("我是第二个接口实现"); 44 } 45 }
根据不同的参数实现不同的类,而且我们可以把参数在工厂类里面写出来。一方面是便于客户查看,明白参数的用法;另外也可以判断客户是不是输入了非法参数,这儿没有判断非法参数。
上面没有展示通过配置文件来实现简单工厂类,实际上就是把例子中需要传入的参数放入了配置文件中,让客户端调用无需再输入参数。在系统配置连接不同数据库的话,应该就是用的这样的方式。本文不在累述。
总结
定义:提供一个创建对象实例的功能,而不用关心其具体实现。被常见的对象可以是接口、抽象类,具体的类。
分析:简单工厂模式,本质上就是在普通代码上添加一个工厂类,创建对象装在了这个类里面,而且对象具体实现不在这个里面。
优点:
- 调用的接口的封装性更好了,没有暴露内部的逻辑实现。
- 解耦,实现了客户端和具体实现类解耦
- 接口的实现类统一管理了。可以扩展也是只要简单工厂类改动就可以了。
缺点:
- 增加了代码复杂度。
虽然这个简单工厂模式非常简单,但是在系统代码里面运用非常普遍。可能你已经运用了,但是自己没有意识到。简单工厂模式的介绍就到这里了。