利用此设计模式完整阐述反射在开发之中的实际意义。
如下例:
package pattern;
//工厂设计模式
interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
@Override
public void eat() {
System.out.println("吃橘子");
}
}
public class FactoryModel {
public static void main(String[] args){
//Fruit f = new Apple();//想吃苹果
Fruit f = new Orange();//想吃橘子
f.eat();
}
}
注意:任何软件设计都不应该以更改用户使用习惯为前提。
主方法实际上是一个客户端,客户端不应该处理任何复杂操作,如果现在想吃哪个new哪个,这样去更换一个子类,修改主方法(客户端代码),合适吗?
此时的客户端代码,一个接口的对象实例化操作直接与一个具体的子类通过关键字new耦合了。所以说要想更换子类,那么必须由客户端去执行。
JVM提供给我们很好的解决耦合方案,所有java程序实际上都是通过JVM间接运行在操作系统上,从而,只要JAM支持不变,那么程序可以任意的移植。如果说现在程序直接与操作系统完全捆绑在一起,那么程序无法修改,也就是传统开发A->B。如果想做松耦合的代码,A–>C–>B
,中间出现一个断层C,而后这个断层负责所有连接操作。
改动后如下:工厂设计–设计中间的环节
//工厂设计模式
interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
@Override
public void eat() {
System.out.println("吃橘子");
}
}
class Factory {
public static Fruit getIns(String className){
if("apple".equals(className)){
return new Apple();
}
if("orange".equals("orange")){
return new Orange();
}
return null;
}
}
public class FactoryModel {
public static void main(String[] args){
Fruit f = Factory.getIns("orange");
f.eat();
}
}
按以上代码修改后可以感受到,客户端调用变容易了。可是它属于简单的工厂设计,这种设计的特点是:直接利用new与if判断来决定使用的子类,适用于接口的子类少的情况,不利于扩充。如果Fruit有无限多个子类,都要在工厂类里面修改就很麻烦了。所以,继续修改代码如下:利用反射解决问题
//修改处
class Factory {
public static Fruit getIns(String className){
Fruit f = null;
try{
Class<?> cls = Class.forName(className);
f = (Fruit) cls.newInstance();
}catch(Exception e){
e.printStackTrace();
}
return f;
}
}
public class FactoryModel {
public static void main(String[] args){
//包.类
Fruit f = Factory.getIns("pattern.Banna");
f.eat();
}
}
这样修改后,即使产生再多的Fruit接口子类,工厂类也同样支持所有子类实例化操作。此时的代码暂时完善了。包.类Fruit f = Factory.getIns("pattern.Banna");
太麻烦,可以使用文件操作简写
工厂模式最重要特点:利用工厂类取得接口的实例化对象,实现接口和子类间解耦合操作。(解耦合;取得接口对象优先使用此模式;使用反射易于扩充)