设计模式:代理模式

来源:互联网 发布:mac卸载itools 编辑:程序博客网 时间:2024/06/06 00:54

代理模式指将目标对象(被代理对象)的一种或者几种功能交给代理对象管理,代理对象对原功能进行增强,并对外提供调用的。

代理模式可以分为静态代理和动态代理,在具体实现上,又存在多种不同的实现方式。

静态代理:在编译阶段生成代理类
动态代理:在运行时动态生成代理类

静态代理

静态代理根据实现方式的不同,可分为继承方式实现和聚合方式实现。

继承方式实现

UML类图

聚合方式实现

UML类图

示例

假设有一辆车,我们需要记录行驶的时间,再记录行驶日志。

行驶接口

public interface Moveable {    void move();}

具有行驶能力的一辆车

public class Car implements Moveable {    @Override    public void move(){        System.out.println("汽车行驶中...");        Thread.sleep(1000);    }}

继承方式

记录行驶时间代理类

public class CarTimeProxy extends Car {    @Override    public void move() {        long startTime = System.currentMillionTime();        super.move();        long endTime = System.currentMillionTime();        System.out.println("本次行驶时间为:"+(endTime-startTime));    }}

记录行驶日志代理类

public class CarTimeLogProxy extends CarTimeProxy {    @Override    public void move() {        System.out.println("开始行驶...");        super.move();        System.out.println("结束行驶...");    }}

客户端

public class Cient {    public void static void main(String[] args) {        Moveable proxy=new CarTimeLogProxy();        proxy.move();    }}

输出结果

开始行驶...汽车行驶中...本次行驶时间为:1000结束行驶...

聚合方式

记录行驶时间代理类

public class CarTimeProxy implements Moveable {    private Moveable targetObject;    public CarTimeProxy(Moveable targetObject){        this.targetObject=targetObject;    }    @Override    public void move() {        long startTime = System.currentMillionTime();        targetObject.move();        long endTime = System.currentMillionTime();        System.out.println("本次行驶时间为:"+(endTime-startTime));    }}

记录行驶日志代理类

public class CarLogProxy implements Moveable {    private Moveable targetObject;    public CarLogProxy(Moveable targetObject){        this.targetObject=targetObject;    }    @Override    public void move() {        System.out.println("开始行驶...");        targetObject.move();        System.out.println("结束行驶...");    }}

客户端

public class Cient {    public void static void main(String[] args) {        Moveable car=new Car();        Moveable carTimeProxy = new CarTimeProxy(car);        Moveable carLogProxy = new CarLogProxy(carTimeProxy);        carLogProxy.move();    }}

需求是多变的

现在需要想记录日志在记录时间!!!于是:

  • 继承方式需要 新建立两个代理类CarLogProxy(继承Car)、CarLogTimeProxy(继承CarLogProxy),然后客户端通过CarLogTimeProxy的实例运行move方法。
  • 聚合方式不需要新增或者修改代理类,只需要在客户端使用的时候调整一下调用顺序,如下:
Moveable car=new Car();Moveable carLogProxy = new CarLogProxy(car);Moveable carTimeProxy = new CarTimeProxy(carLogProxy );carTimeProxy .move();

由此可以看出,聚合方式更具有灵活性,更能适应多变的需求。

动态代理

借助JDK内置的Proxy实现

代码示例:

public interface IObject {    void doSomething();}public class TargetObject implements IObject {    @Override    public void doSomething() {        System.out.println("I can do something...");    }}public class JdkDynamicProxy implements InvocationHandler {    // 被代理类    private TargetObject targetObject;    // 代理操作    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("Method start...");        Object result = method.invoke(targetObject, args);        System.out.println("Method stop...");        return result;    }    // 获取代理对象    public Object getProxyObject(TargetObject targetObject) {        this.targetObject = targetObject;        Object proxyObject = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),                targetObject.getClass().getInterfaces(), this);        return proxyObject;    }}public class Client {    public static void main(String[] args) {        JdkDynamicProxy jdkDynamicProxy = new JdkDynamicProxy();        IObject object = (IObject) jdkDynamicProxy.getProxyObject(new TargetObject());        object.doSomething();    }}

特点:
- 需要实现InvocationHandler接口实现代理操作,通过Proxy.newInstance获取代理实例
- 目标类(被代理类)和生成的代理类实现同一接口

借助cglib实现

public class TargetObject {    public void doSomething() {        System.out.println("I can do something...");    }}public class CglibDynamicProxy implements MethodInterceptor {    private TargetObject targetObject;    // 代理的具体操作    @Override    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {        System.out.println("Method start...");        Object result = methodProxy.invoke(this.targetObject, args);        System.out.println("Method stop...");        return result;    }    // 获取代理对象    public Object getProxyObject(TargetObject targetObject) {        this.targetObject = targetObject;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(targetObject.getClass());        enhancer.setCallback(this);        return enhancer.create();    }}public class Client {    public static void main(String[] args) {        CglibDynamicProxy jdkDynamicProxy = new CglibDynamicProxy();        TargetObject targetObject = (TargetObject) jdkDynamicProxy.getProxyObject(new TargetObject());        targetObject.doSomething();    }}

特点:

  • 需要实现MethodInterceptor接口实现代理操作
  • 代理类是被代理类的子类,所以被代理类不能死final的
  • 被代理类不需要继承某个接口

参考文献:http://www.cnblogs.com/best/p/5679656.html