飞艳小屋

程序--人生--哲学___________________欢迎艳儿的加入

BlogJava 首页 新随笔 联系 聚合 管理
  52 Posts :: 175 Stories :: 107 Comments :: 0 Trackbacks
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

利用反射实现的动态加载


Bromon原创 请尊重版权

最近在成都写一个移动增值项目,俺负责后台server端。功能很简单,手机用户通过GPRS打开Socket与服务器连接,我则根据用户传过来的数据做出响应。做过似项目的兄弟一定都知道,首先需要定义一个似于MSNP的通讯协议,不过今天的话题是如何把这个系统设计得具有高度的扩展性。由于这个项目本身没有进行过较为完善的客户沟通和需求分析,所以以后肯定会有很多功能上的扩展,通讯协议肯定会越来越庞大,而我作为一个不那么勤快的人,当然不想以后再去修改写好的程序,所以这个项目是实践面向对象设计的好机会。

首先定义一个接口来隔离

package org.bromon.reflect;

public interface Operator

{

public java.util.List act(java.util.List params)

}

根据设计模式的原理,我们可以为不同的功能编写不同的,每个都继承Operator接口,客户端只需要针对Operator接口编程就可以避免很多麻烦。比如这个

package org.bromon.reflect.*;

public class Success implements Operator

{

public java.util.List act(java.util.List params)

{

List result=new ArrayList();

result.add(new String(“操作成功”));

return result;

}

}

我们还可以写其他很多,但是有个问题,接口是无法实例化的,我们必须手动控制具体实例化哪个,这很不爽,如果能够向应用程序传递一个参数,让自己去选择实例化一个,执行它的act方法,那我们的工作就轻松多了。

很幸运,我使用的是Java,只有Java才提供这样的反射机制,或者说内省机制,可以实现我们的无理要求。编写一个配置文件emp.properties:

#成功响应

1000=Success

#向客户发送普通文本消息

2000=Load

#客户向服务器发送普通文本消息

3000=Store

文件中的键名是客户将发给我的消息头,客户发送1000给我,那么我就执行Success的act方法,似的如果发送2000给我,那就执行Load的act方法,这样一来系统就完全符合开闭原则了,如果要添加新的功能,完全不需要修改已有代码,只需要在配置文件中添加对应规则,然后编写新的,实现act方法就ok,即使我弃这个项目而去,它将来也可以很好的扩展。这样的系统具备了非常良好的扩展性和可插入性。

下面这个例子体现了动态加载的功能,程序在执行过程中才知道应该实例化哪个

package org.bromon.reflect.*;

import java.lang.reflect.*;

public class TestReflect

{

//加载配置文件,查询消息头对应的

private String loadProtocal(String header)

{

String result=null;

try

{

Properties prop=new Properties();

FileInputStream fis=new FileInputStream("emp.properties");

prop.load(fis);

result=prop.getProperty(header);

fis.close();

}catch(Exception e)

{

System.out.println(e);

}

return result;

}

//针对消息作出响应,利用反射导入对应的

public String response(String header,String content)

{

String result=null;

String s=null;

try

{

/*

* 导入属性文件emp.properties,查询header所对应的的名字

* 通过反射机制动态加载匹配的,所有的都被Operator接口隔离

* 可以通过修改属性文件、添加新的(继承MsgOperator接口)来扩展协议

*/

s="org.bromon.reflect."+this.loadProtocal(header);

//加载

Class c=Class.forName(s);

//创建的事例

Operator mo=(Operator)c.newInstance();

//构造参数列表

Class params[]=new Class[1];

params[0]=Class.forName("java.util.List");

//查询act方法

Method m=c.getMethod("act",params);

Object args[]=new Object[1];

args[0]=content;

//调用方法并且获得返回

Object returnObject=m.invoke(mo,args);

}catch(Exception e)

{

System.out.println("Handler-response:"+e);

}

return result;

}

public static void main(String args[])

{

TestReflect tr=new TestReflect();

tr.response(args[0],”消息内容”);

}

}

测试一下:java TestReflect 1000

这个程序是针对Operator编程的,所以无需做任何修改,直接提供Load和Store,就可以支持2000、3000做参数的调用。

有了这样的内省机制,可以把接口的作用发挥到极至,设计模式也更能体现出威力,而不仅仅供我们饭后闲聊。

 

posted on 2006-06-06 12:51 天外飞仙 阅读(324) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: