Java设计模式笔记之代理模式

来源:互联网 发布:java 多泛型的 编辑:程序博客网 时间:2024/05/22 13:19

1.代理模式

代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。


2.代理的种类

如果按照使用目的来划分,代理有以下几种:

(1)远程代理(Remote):为一个位于不同的地址空间的对象提供一个局域代表对象。

(2)虚拟代理(Virtual):根据需要创建一个资源消耗比较大的对象,使得此对象只在需要时才会被真正创建,之前使用的是代理。

(3)Copy-on-write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。

(4)保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

(5)Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端乐意共享这些结果。

(6)防火墙(firewall)代理:保护目标,不让恶意用户接近。

(7)同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。

(8)智能引用(Smart Referenc)代理:当一个对象被引用是,提供一些额外的操作。


3.代理模式的结构

类图:


抽象主题(Subject):定义了实际对象和代理对象的共同行为,使得能使用实际对象的地方都能使用代理。

代理主题(Proxy):代理类,持有一个被代理的类的引用,可以自由操作被代理对象;用户和被代理类相同的接口,在任何环境中都可以代替被代理类;控制对被代理对象的引用;在引用被代理对象的方法前或者后,一般会执行一些额外操作。

真实主题(RealSubject):被代理类。


4.示例源码

Subject.java

package com.patterns.proxy;abstract public class Subject{    abstract public void request();}

ProxySubject.java

package com.patterns.proxy;public class ProxySubject extends Subject {    private RealSubject realSubject;public ProxySubject(){}public void request(){        preRequest();if( realSubject == null )        {realSubject = new RealSubject();}        realSubject.request();        postRequest();}    private void preRequest()    {        System.out.println("pre request from proxy");    }    private void postRequest()    {        System.out.println("after requet from proxy");    }}

RealSubject.java

package com.patterns.proxy;public class RealSubject extends Subject {public RealSubject(){ }public void request(){ System.out.println("From real subject.");}}

Client.java

package com.patterns.proxy;public class Client{  private static Subject subject;    static public void main(String[] args){ subject = new ProxySubject();subject.request();}}

运行结果:

pre request from proxy
From real subject.
after requet from proxy


代理调用时,在实际对象的调用的前后加入了一些自己的操作(智能引用)。


5.动态代理

在Java中,提供了支持代理模式的接口,可以在运行时间内创建代理对象。

package com.patterns.proxy.reflect;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.ArrayList;import java.util.List;/** *  *与代理类相关联的InvocationHandler对象  * */public class ListProxy implements InvocationHandler{    private Object proxyobj;    public ListProxy(Object obj)    {        proxyobj = obj;    }    /**     *创建代理对象的工厂方法      *     */public static Object factory(Object obj)    {Class<?> cls = obj.getClass();        return Proxy.newProxyInstance( cls.getClassLoader(),            cls.getInterfaces(),//指定被代理的接口函数            new ListProxy(obj) );//指定InvocationHandler    }/** * 调用被代理的接口函数的处理,可以添加一些额外的操作 */    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable    {System.out.println("before calling " + method);        if (args != null)        {for (int i=0; i<args.length; i++)            {                System.out.println(args[i] + "");            }}        Object o = method.invoke(proxyobj, args);System.out.println("after calling " + method);        return o;    }   public static void main(String[] args)    {List<String> v = null;        v = (List<String>) factory(new ArrayList<String>());        v.add("New");        v.add("York");    }}

创建动态代理的过程

(1)指明一系列接口来创建代理对象,上例在工厂方法中指明使用传入参数的接口,如果没有接口的话,本例不适用。

(2)继承InvocationHandler实现一个代理处理器,在创建代理时使用,系统会把它和指定的接口做关联。

(3)invoke函数的改写,invoke函数会拦截被指定的接口,并执行自己的内容。

(4)在运行时,新建代理对象,并运行。

上例中运行结果:

before calling public abstract boolean java.util.List.add(java.lang.Object)
New
after calling public abstract boolean java.util.List.add(java.lang.Object)
before calling public abstract boolean java.util.List.add(java.lang.Object)
York
after calling public abstract boolean java.util.List.add(java.lang.Object)

拦截了被指定的List的接口,包括add();所以在 v.add("New");  v.add("York");时,其实是执行了ListProxy中的invoke的内容



原创粉丝点击