读《研磨设计模式》-代码笔记-代理模式_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 读《研磨设计模式》-代码笔记-代理模式

读《研磨设计模式》-代码笔记-代理模式

 2012/8/21 11:13:56  bylijinnan  程序员俱乐部  我要评论(0)
  • 摘要:声明:本文只为方便我个人查阅和理解,详细的分析以及源代码请移步原作者的博客http://chjavach.iteye.com/importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;/**下面的代码关注两种代理:*1.虚代理*2.保护代理*///订单类接口interfaceIOrder{voidsetName(Stringname)
  • 标签:笔记 研磨设计模式 代码 模式 代理 设计 设计模式 代理模式
声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/




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

/*
 * 下面的代码关注两种代理:
 * 1.虚代理
 * 2.保护代理
 */

//订单类接口
interface IOrder {
	
	void setName(String name);
	
	void setID(String id);
	
	String getName();
	
	String getID();
	
}

class Order implements IOrder {
	
	private String id;
	
	private String name;
	
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String getID() {
		return this.id;
	}

	public void setID(String id) {
		this.id = id;
	}
	
}


class OrderProxy implements IOrder {

	private Order order;
	
	private boolean nameLoaded;
	
	public OrderProxy(Order order) {
		this.order = order;
		this.nameLoaded = false;
	}
	
	/*
	 * 1、虚代理
	 * a. 客户查询订单信息时,只查询客户要求的信息:订单ID(假设这个查询比较快)
	 * b. 只有当用户要求更详细的信息(假设只是一个订单名称)时,才再次到数据库查询
	 * 这样做的原因是,通常查询“详细信息”时,会花费更多的时间和空间,有点“延迟加载”的感觉
	 */
	private void loadName() {
		if (!nameLoaded) {
			System.out.println("request name but no name, fetch it from database:");
			String name = "aName";		//模拟数据库操作
			order.setName(name);
			this.nameLoaded = true;
		}
	}

	public String getID() {
		return order.getID();
	}

	/*
	 * 2.保护代理,可以在这里加上条件,符合则调用真实的order的方法。例如只有订单创建者能修改订单名称
	 */
	public void setName(String name) {
		boolean canChangeName = true;		//根据实际设置
		if (canChangeName) {
			order.setName(name);
			System.out.println("Request accepted. Name changed.");
		}
	}

	public void setID(String id) {
		order.setID(id);
	}

	public String getName() {
		if (!nameLoaded) {
			this.loadName();
		}
		return this.order.getName();
	}
	
}


public class ProxyPattern {

	public static void main(String[] args) {
		
		//1.静态代理
		ProxyPattern p = new ProxyPattern();
		IOrder order = p.getOrder();
		System.out.println("id:" + order.getID());
		
		//测试虚代理。如果“客户”没有调用getName,那“到数据库查询name”这个操作就可以不执行了
		System.out.println("name:" + order.getName());
		
		//测试保护代理
		order.setName("newName");
		System.out.println(order.getName());
		
		//2.动态代理
		//准备测试数据
		Order order2 = new Order();
		order2.setID("originalID");
		order2.setName("originalName");
		DynamicProxy dProxy = new DynamicProxy();
		IOrder iOrder = dProxy.getProxyOrder(order2);
		iOrder.setID("anotherID");
		iOrder.setName("anotherName");
		System.out.println(iOrder.getID() + ","+ iOrder.getName());
	}

	//模拟从数据库查询Order
	public IOrder getOrder() {
		//这里创建的是代理,而非真实的Order
		//IOrder order = new Order();
		OrderProxy proxy = new OrderProxy(new Order());
		System.out.println("simple info. Only fetch order's id from database:");
		String id = "aID";		//模拟从数据库取得ID
		proxy.setID(id);
		return proxy;
	}
}


//=======================以上实现代理的方式称为静态代理===========================================

/**
 * JDK里面的InvocationHandler来实现代理,称为动态代理
 */
class DynamicProxy implements InvocationHandler{

	private IOrder order;
	
	public IOrder getProxyOrder(Order order) {
		this.order = order;
	    //把真正的订单对象和动态代理关联起来
		IOrder iOrder = (IOrder) Proxy.newProxyInstance(order.getClass().getClassLoader(),
											              order.getClass().getInterfaces(),
											              this);
       return iOrder;
	}
	
	public Object invoke(Object obj, Method method, Object[] aobj) throws Throwable {
		Object result = null;
		
		//假设不允许执行setID操作
		if (method.getName().equalsIgnoreCase("setID")) {
			System.out.println(method.getName() + ":Access denied.");
		} else {
			//result = method.invoke(obj, aobj);		//不能这样写。要调用真实的order:
			result = method.invoke(order, aobj);
		}
		return result;
	}
	
}


发表评论
用户名: 匿名