工厂设计模式是java开发中使用的最多的一种设计模式。本程序首先定义的一个表示水果的fruit接口。然后为Fruit定义的一个apple子类,在主类中通过Apple类实例化Fruit接口对象,所以当利用Fruit的接口对象调用eat( )方法时调用的是被子类覆写过的方法。
本程序是读者所熟知的程序结构。因为接口不能直接被实例化对象,所以必须利用向上转型技术,通过子类实例化父类接口对象。但是这样做并不是真的合理。
如果要确认一个代码的编写发编写风格是否良好,应遵从于以下两个标准。
- 客户端(现为主方法)调用简单,不需要关注具体细节;
- 程序代码的修改不影响客户端的使用。即使用者可以不去关心代码是否变更
根据以上两个标准就可以发现本程序设计上的问题,本程序在取得接口的实例化对象时,明确的指明了实用的子类fruit,Fruit f = new Apple()。关键的问题就出现在关键字new上,因为一个接口不可能只有一个子类,所以fruit也可能产生多个子类对象。而一旦要扩展子类,客户端中使用也就可能还会与新的子类有关系。下面通过程序来建立一个Orange子类
public class Orange implements Fruit{
@Override
public void eat() {
System.out.println("Andy also like eat Orange");
}
}
定义新的子类
本程序的客户端上想要得到这个新的子类对象,就需要修改代码
public class TestFruit {
public static void main(String[] args) {
Fruit f = new Apple(); // 子类实例化父类对象
f.eat(); // 调用被重写过的方法
Fruit f01 = new Orange();
f01.eat();
}
}
本程序客户端的代码更改的一个子类orange,所以修改了客户端的代码,将Apple子类替换为了Orange子类。
这个时候如果有更多的子类呢?难道每次去修改实例化接口的子类吗?在这个过程中,客户端关心的事情只有一件,如何去获取到Fruit接口对象,至于说这个对象是被哪个子类所实例化的,客户端根本就不需要知道,所以在整个代码的关键自new是最大的问题。
那么该如何去解决关键字new所带来的耦合度问题呢?不妨回顾一下JVM的核心原理。在java中,JVM为了解决程序与操作系统的耦合问题,在程序与操作系统之间加了一个中间过渡层——JVM。由于JVM匹配不同的操作系统,JVM的核心支持不变,程序就可以在任意的操作系统间进行移植,所以解决办法就产生了。
想办法让客户端看见接口,不让其看到子类,这就需要一个中间的工具类来取得接口对象。这样客户端就不需要关心接口子类,只需要获得工厂类(factory)程序类就可以取得接口的对象.
同时这也是spring开发框架设计的核心理念: 实际上这种耦合问题在很多项目开发中都会存在很多开发者面对这种愈合问题。往往会采用大量的结构设计进行回避,可是这样的代码维护成本太高了,所以在java开发中有一个spring框架,其核心目的就是解决这种代码耦合问题。
增加一个工厂类过度。
public class Factory {
public static Fruit getInstance(String className){
if("apple".equals(className)){
return new Apple();
}
if("orange".equals(className)){
return new Orange();
}else {
return null;
}
}
}
public class TestFruit02 {
public static void main(String[] args) {
Fruit f00 = Factory.getInstance("orange");// 通过工厂类取得指定标记的对象
f00.eat();
}
}
本程序在客户端的操作上取消了关键字new的使用,而factory get instance()方法只根据指定子类的标记取得。实例化对象这样客户端不需要再关注具体子类,也不需要关注factory是怎样处理的,只需要关注如何取得了接口对象,并且操作这样的设计的开发中,就被称为工厂设计模式。