静态代理模式中,真实角色必须是事先已经存在的,并将其作为代理对象的内部属性,并且真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀。那么,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
设计模式
1.静态代理模式
使用场合:
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
涉及的角色:
抽象角色:
声明真实对象和代理对象的共同接口;
代理角色:
代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:
代理角色所代表的真实对象,是我们最终要引用的对象。
最好的老师是代码,下面是本人敲的一个静态代理代码示例?
Java代码
|
package com;
/**
* 车站接口-【抽象角色】
*
* @author abing
*
*/
interface Station {
void sellTicks();// 卖票
void transport();// 运输乘客
}
/**
* 火车站实现类-【具体角色】
*
* @author abing
*
*/
class TrainStationImpl implements Station {
@Override
public void sellTicks() {
System.out.println("TrainStation sell tickets");
}
@Override
public void transport() {
System.out.println("TrainStation transport passenger");
}
}
/**
* 该类做为火车站的一个代理直接供客户端调用-【代理角色】
*
* @author abing
*
*/
class StationProxy implements Station {
Station sta = new TrainStationImpl();
@Override
public void sellTicks() {
sta.sellTicks();//代理类中调用真实角色的方法。
}
public void otherOperate() {
System.out.println("do some other things...");
}
@Override
public void transport() {
System.out.println("StationProxy can not transport");
}
}
/**
* 客户端测试类
*
* @author abing
*
*/
public class StaticProxyDemo {
public static void main(String[] args) {
Station station = new StationProxy();//客户端直接操作代理类,避免了客户端与真实类的直接交涉
station.sellTicks();
}
} |
2.动态代理模式
静态代理模式中,真实角色必须是事先已经存在的,并将其作为代理对象的内部属性,并且真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀。那么,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
动态代理必需用到以下两个类。
(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。用于完成真实角色中方法的调用。
(2).Proxy:该类即为动态代理类,作用类似于静态代理模式的代理类
最好的老师是代码,下面是本人敲的一个动态代理代码示例
Java代码
|
package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 车站接口-【抽象角色】
* @author abing
*
*/
interface Station {
void sellTicks();// 卖票
}
/**
* 火车站实现类-【具体角色】
* @author abing
*
*/
class TrainStationImpl implements Station {
@Override
public void sellTicks() {
System.out.println("TrainStation sell tickets");
}
}
/**
* 使用动态代理模式必须实现InvocationHandler接口,该接口中仅定义了一个方法:
* invoke(Object obj,Method method, Object[] args)。
* 在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组
*
* @author abing
*
*/
class InvocationHandlerImpl implements InvocationHandler {
Object proxyobj;
public InvocationHandlerImpl(Object object) {
this.proxyobj = object;
}
@Override
public Object invoke(Object obj, Method method, Object[] args)
throws Throwable {
System.out.println("start doing .........");
method.invoke(proxyobj, args);//调用被代理对象proxyobj的方法method,传入一个参数组args
System.out.println("stop doing .........");
return null;
}
}
/**
* 客户端测试类
* @author abing
*
*/
public class DynamicProxyDemo {
public static void main(String[] args) {
Station stationImpl = new TrainStationImpl();//将要被代理的真实对象
/**
* 动态代理就好处在这里,不管这里是要代理什么对象,I
* nvocationHandlerImpl与Proxy中代码都不必改变,
* 都是用下面同样的方式去产生代理对象
*/
InvocationHandler handler = new InvocationHandlerImpl(stationImpl);
//用InvocationHandler的实现类包装真实的被代理角色
ClassLoader loader = handler.getClass().getClassLoader();
//获取当期那java程序的类装在器Classloadler
Class[] interfaces = stationImpl.getClass().getInterfaces();
//获取被代理角色实现的所有接口
/**
* Proxy类是动态代理模式涉及到的另一个重要的类,该类即为动态代理类,
*作用类似于静态代理模式中的代理类StationProxy,
* 它有一个重要方法tatic Object newProxyInstance(ClassLoader loader, Class[] interfaces,
*InvocationHandler h):返回代理类的一个实例。
* 其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组,
*传递此参数以使产生的代理对象可以当做真实类任意实现接口的子类来用,
* h是调用处理器InvocationHandler。
*/
Station station = (Station) Proxy.newProxyInstance(loader, interfaces,handler);
station.sellTicks();//将会去执行DynamicProxy的invoke方法,完成对目标对象方法的调用
}
} |
|