工厂模式简介:
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽,达到提高灵活性的目的。工厂模式共有三种,简单工厂(simple factory),多态工厂(factory method),抽象工厂(abstract factory).大家如果对工厂模式不熟悉的话,可以参考另一篇博文(http://blog.csdn.net/rowandjj/article/details/8785050)。
下面进入本次主题:
在我们实际项目开发时,可能对于某一接口有不同的实现方式,或者说,项目需求发生改变时,我们需要对接口重新实现以满足新的需求。这时我们可以充分利用多态的特性使引用指向新的实现类,这样只需修改几行代码即可,但是我们想象一下,当项目足够大,代码达到几万行,而且不止一处需要修改时,我们的工作将会变得很麻烦,而且还容易出现失误。所以我们并不建议修改源代码。那如何才能保证在尽量少的修改代码的前提下完成这项工作呢?我们想到了反射可以通过类名构建一个类的实例,我们可以把类名放在一个配置文件中作为一个键值对存储,当需要修改实现类时,只需要修改该键所对应的的值即可,是不是很酷呢?
下面通过一个简单的例子实现之。
首先我们定义一个接口和它的两个实现类(实际情况可能有多个实现类):
package factory; public interface Car { public void drive(); }
实现类1:
package factory; public class CarImpl01 implements Car { @Override public void drive() { // TODO 自动生成的方法存根 System.out.println("this is a benz car"); } }
实现类2:
package factory; public class CarImpl02 implements Car { @Override public void drive() { // TODO 自动生成的方法存根 System.out.println("this is a bmw car"); } }
下面重点来了,我们在项目下新建一个配置文件CarImpl.properties,文件中定义这样一个键值对:
carImplName = factory.CarImpl01
接下来,我们创建一个工厂类用来制造汽车:
package factory; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class Factory { private static Car car = null; private static Factory instance = new Factory(); // 上面两行代码位置不可以互换,否则会抛出空指针异常(联系类的初始化顺序) private Factory()//单例 { String filename = "src\\factory\\CarImpl.properties"; InputStream inStream = null; try { inStream = new FileInputStream(new File(filename)); Properties prop = new Properties(); prop.load(inStream); String className = prop.getProperty("carImplName"); car = (Car)Class.forName(className).newInstance(); } catch (FileNotFoundException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); /* 这里异常处理过于简单,实际开发需要针对不同业务逻辑编写不同的异常处理方式 */ } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (InstantiationException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (IllegalAccessException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } public static Factory getInstance() { return instance; } public Car buildCar() { return car; } }
好了,大功告成,我们测试一下功能吧。
package factory; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Car car = Factory.getInstance().buildCar();//要先获取Factory的实例对象! car.drive(); } }
现在我们想生成CarImpl02对象,不必更改代码,只需注释掉刚才配置文件,像这样:
#carImplName = factory.CarImpl01 carImplName = factory.CarImpl02
是不是很方便呢?