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

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的内容



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值