具体内容
实际上工厂设计模式是一种实例化对象的标准结构。
在正常操作中,如果想要实例化一个接口对象,往往会直接利用关键字 new。
//定义一个水果接口
interface Fruit{
public void eat();
}
//如果想要吃苹果,就实现吃水果接口
class Apple implements Fruit{
public void eat() {
System.out.println("吃苹果");
}
}
//如果想要吃橘子,就实现吃橘子接口
class Orange implements Fruit{
public void eat() {
System.out.println("吃橘子");
}
}
//测试
public class Demo {
public static void main(String[] args) {
Fruit f=new Orange();
f.eat();
}
}
以上代码中,如果想要吃苹果,就new一个Apple,如果想要吃橘子,就new一个橘子。
但是这时候出现了一个问题,即主方法实际上就是一个客户端,客户端不应该处理任何的复杂操作。
如果现在想要更换一个子类,那么就需要去修改主方法(客户端代码),合适吗?
任何的软件设计都不应该以更改用户的使用习惯为前提,但是以上代码,想要更换子类,必须由客户端去执行。因为此时的客户端代码,一个接口的对象实例化操作直接与一个具体的子类通过关键字new耦合了。
解决方案
对于以上出现的问题,其实JVM已经提供给了我们很好的解决方案,所有的Java程序实际上都是通过JVM来间接的运行在操作系统上,从而,只要JVM的支持不变,那么程序可以任意的移植,如果说现在的程序直接与操作系统完全捆绑在一起。那么程序将无法修改,也就是说,传统的开发好比是:程序直接与操作系统进行捆绑
,如果要想做一个松耦合的代码,程序通过JVM间接对操作系统进行操作
。中间出现一个断层,而后,这个断层负责处理所有的连接操作。
范例:编写工厂设计——设计中间的环节
//为以上代码添加中间环节(工厂)
class Factory{
public static Fruit getInstance(String className){
if("apple".equalsIgnoreCase(className)){
return new Apple();
}
if("orange".equalsIgnoreCase(className)){
return new Orange();
}
return null;
}
}
//测试
public class Demo {
public static void main(String[] args) {
Fruit fruit = Factory.getInstance("orange");
fruit.eat();
}
}
要想取得对象,只要通过Factory.getInstance()方法即可,可以感受到,客户端的代码调用很容易了,只需要传入一个字符串就可以利用工厂类取得一个子类的实例化对象。
以上代码的问题
以上的代码属于简单的工厂设计,这种工厂设计的特点:直接利用关键字 new 与if 判断来决定使用的子类,这种情况适合于接口的子类少的情况。但是不利于扩充。
比如要添加一个樱桃类,那么就要在工厂类中添加樱桃的 if 代码块。
如果说Fruit有无限多个子类那么这个工厂类的修改就非常的麻烦。所以一般在这样的情况下,可以利用反射来解决问题。
通过反射实现工厂
使用反射对以上的工厂进行重新构造
class Factory{
public static Fruit getInstance(String className){
Fruit fruit=null;
try {
Class<?> clazz = Class.forName(className);
fruit= (Fruit)clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return fruit;
}
}
测试代码
public class Demo {
public static void main(String[] args) {
Fruit fruit = Factory.getInstance("com.pdsu.test.Apple");
fruit.eat();
}
}
如果按照此方式,即使产生了再多的 Fruit 接口子类,工厂类也可以支持所有的子类实例化操作。此时的代码才算是占时完善了。
总结
工厂设计模式最重要的特定:利用工厂类取得接口的实例化对象,实现接口和子类间的解耦合操作。
如果遇到接口对象的取得,一定要优先考虑到使用此模式,同时使用反射的工厂设计模式更易于扩,充,完全不受限于扩充子类的影响。