java 代理模式

代理模式简单说就是当客户端需要调用某个对象时,实际上不关心是否准确得到该对象,它只要一个能提供改功能的对象就可以了。在这种模式下,系统会为某个对象提供一个代理对象,并有代理对象控制对源对象的控制。总之,只要客户端不能或不想直接访问被调用对象,如要创建一个开销很大的系统对象,调用远程主机上的对象,或目标对象不够强大等,都可以采用代理模式。

下面示范一个简单的代理模式,首先实现一个借口Subject

package impl;

public interface Subject {

public void proxy();
}

为这接口提供一个实现类

package impl;

public class RealSubject implements Subject {

public RealSubject(){
try{
Thread.sleep(6000);//程序暂停6秒模拟系统开销
}catch(Exception e){
e.printStackTrace();
}
}

@Override
public void proxy() {
// TODO Auto-generated method stub
System.out.println("this is RealSubject......");
}

}

代理类
package impl;

public class MyProxy implements Subject {

RealSubject rs;

public MyProxy(RealSubject rs){
this.rs=rs;
}

@Override
public void proxy() {

if(null == rs){
rs = new RealSubject();
}
rs.proxy();
}
}

客户端Client
package impl;


public class Client {

public static void main(String args[]){
long start = System.currentTimeMillis();
MyProxy proxy = new MyProxy(null);
// proxy.proxy();
System.out.println(System.currentTimeMillis()-start);
}
}

上面的就是一个简单的代理模式,初始化Subject非常快,因为程序并没有真正创建MySubject对象,只是等到了要调用MySubject的方法,如proxy()方法的时候才会创建。在某些情况下,系统可能永远都不会真正使用proxy方法,意味着系统不用创建MySubject对象,这就大大提高了系统的性能。

使用代理模式还能够增强已有对象的功能,通过java的Proxy和InvocationHandler就可以实现动态代理,并增强原有对象的功能。使用上面的Subject和MySubject,现在增加一个功能类TxUtil来模拟事务功能,实际上就是个拦截器类。
package impl;

public class TxUtil {

public void beginTx(){
System.out.println("模拟事务的开始.......");
}

public void endTx(){
System.out.println("模拟事务的结束.......");
}
}

创建MyInvokationHandler类,它是InvocationHandler实现类,该实现类的invoke方法将会作为代理对象的方法实现,也就是说,invoke()方法将作为动态代理对象所有方法的实现体。
package impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvokationHandler implements InvocationHandler {

//需要被代理的对象
private Object targer;
public void setTarget(Object o){
targer = o ;
}

//执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

TxUtil tx = new TxUtil();
tx.beginTx(); //1
Object result = method.invoke(targer, args); //2
tx.endTx(); //3
return result;
}

}

上面1行会调用模拟的开始事务方法,2行通过反射回调被代理对象的目标方法,3行调用模拟的结束事务方法,这样,就给原有方法增加了事务的功能。
下面实现一个MyProxyFactory类,专为指定的target生成动态代理实例
package impl;

import java.lang.reflect.Proxy;

public class MyProxyFactory {

//为指定targer生成动态代理对象
public static Object getProxy(Object target) throws Exception{
MyInvokationHandler handler = new MyInvokationHandler();
handler.setTarget(target);
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),handler);
}
}

该动态代理工厂类提供了一个getProxy()方法,该方法为target生成了一个动态代理对象,当调用动态代理对象的指定方法时,实际上变为执行MyInvokationHandler的invoke方法。当我们还要增强功能时,只要增加另外的拦截器类,并在invoke中调用即可。
下来实现个测试类
package impl;

public class Test {

public static void main(String args[]) throws Exception{
//创建一个原始的RealSubject对象,作为target
Subject target= new RealSubject();
//以指定的target来创建动态代理
Subject subject = (Subject)MyProxyFactory.getProxy(target);
subject.proxy();
}

}

运行结果:
模拟事务的开始.......
this is RealSubject......
模拟事务的结束.......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值