工厂模式简介:
工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽,达到提高灵活性的目的。工厂模式共有三种,简单工厂(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
是不是很方便呢?