《JAVA与模式》26天系列—第10天—代理模式

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


代理模式的结构

  所谓代理,就是一个人或者机构代表另一个人或者机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

  代理模式类图如下:

  在代理模式中的角色:

  ●  抽象对象角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。

  ●  目标对象角色:定义了代理对象所代表的目标对象。

  ●  代理对象角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。

源代码

  抽象对象角色

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-26 上午10:40:16
 * 
 * @类说明 :抽象对象角色
 */
public abstract class AbstractObject {
	// 操作
	public abstract void operation();
}


 

  目标对象角色

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-26 上午10:40:46
 * 
 * @类说明 :目标对象角色
 */
public class RealObject extends AbstractObject {
	@Override
	public void operation() {
		// 一些操作
		System.out.println("一些操作");
	}
}


 代理对象角色

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-26 上午10:41:06
 * 
 * @类说明 :代理对象角色
 */
public class ProxyObject extends AbstractObject {
	RealObject realObject = new RealObject();

	@Override
	public void operation() {
		// 调用目标对象之前可以做相关操作
		System.out.println("before");
		realObject.operation();
		// 调用目标对象之后可以做相关操作
		System.out.println("after");
	}
}


 

  客户端

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-26 上午10:41:32
 * 
 * @类说明 :客户端:代理对象将客户端的调用委派给目标对象,在调用目标对象的方法之前跟之后都可以执行特定的操作。
 */
public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		AbstractObject obj = new ProxyObject();
		obj.operation();
	}

}

 

运行一下:

before
一些操作
after


 从上面的例子可以看出代理对象将客户端的调用委派给目标对象,在调用目标对象的方法之前跟之后都可以执行特定的操作。

 

采用Java代理模式,代理类通过调用委托类对象的方法,来提供特定的服务。委托类需要实现一个业务接口,代理类返回委托类的实例接口对象。

按照代理类的创建时期,可以分为:静态代理和动态代理。

所谓静态代理: 指程序员创建好代理类,编译时直接生成代理类的字节码文件。

所谓动态代理: 在程序运行时,通过反射机制动态生成代理类。

 

静态代理类的特点: 代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。而且代理类只能为特定的接口(Service)服务。

动态代理: 代理类需要实现InvocationHandler接口。

使用场合举例: 如果需要委托类处理某一业务,那么我们就可以先在代理类中,对客户的权限、各类信息先做判断,如果不满足某一特定条件,则将其拦截下来,不让其代理。

 

上代码:

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-27 上午11:11:47
 * 
 * @类说明 :
 */
public interface Service {
	/**
	 * 查询日期
	 */
	public String queryDate();

	/**
	 * 计算两个整数之差
	 */
	public int sub(int a, int b);

}


 

package com.bankht.Proxy;

import java.util.Date;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-27 上午11:12:30
 * 
 * @类说明 :
 */
public class ServiceImpl implements Service {

	@Override
	public String queryDate() {
		return new Date().toString();
	}

	@Override
	public int sub(int a, int b) {
		return a - b;
	}

	public String ownMethod() {
		System.out.println("It's my own method");
		return "admin";
	}
}


 

package com.bankht.Proxy;

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

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-27 上午11:07:15
 * 
 * @类说明 :
 */
public class ServiceProxy implements InvocationHandler {
	private Object target;

	public ServiceProxy(Object target) {
		this.target = target;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object result = null;
		if (!(target instanceof ServiceImpl)) {
			System.out.println("不能代理该对象");
			return result;
		} else if (!((ServiceImpl) target).ownMethod().equals("admin")) {
			System.out.println("权限不够");
			return result;
		}
		result = method.invoke(target, args);
		return result;
	}

	/**
	 * @param target
	 * @return 返回委托类接口的实例对象
	 */
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
}


 

package com.bankht.Proxy;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-6-27 上午11:10:10
 * 
 * @类说明 :
 */
public class ServiceTest {
	public static void main(String[] args) {
		// 创建委托类实例,即被代理的类对象
		ServiceImpl target = new ServiceImpl();
		// 创建动态代理类
		ServiceProxy proxy = new ServiceProxy(target);
		Service service = (Service) proxy.getProxyInstance();
		String date = service.queryDate();
		System.out.println(date);
		int result = service.sub(10, 20);
		System.out.println("10-20 = " + result);
	}
}


运行一下:

It's my own method
Wed Jun 27 11:27:13 CST 2012
It's my own method
10-20 = -10


如果将

ServiceImpl.java 中ownMethod()方法

return "admin";

改为:

return "ak47";

 

运行一下:

It's my own method
权限不够
null
It's my own method
权限不够
Exception in thread "main" java.lang.NullPointerException
	at $Proxy0.sub(Unknown Source)
	at com.bankht.Proxy.ServiceTest.main(ServiceTest.java:18)


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值