`

设计模式--代理模式

阅读更多

代理模式

代理模式 参考了iteye网友的一篇文章《java设计模式之——代理模式》

以下代码根据该思想改编

 

接口

public interface KindWoman {
	
	public void makeEyesWithMan();

	public void happyWithMan();
	
}

 

 实现类

public class Beauty implements KindWoman {

	@Override
	public void happyWithMan() {
		System.out.println("游戏...");
	}

	@Override
	public void makeEyesWithMan() {
		System.out.println("抛媚眼...");
	}
}

 

 代理类

public class UglyWoman implements KindWoman {

	private KindWoman kindWoman;

	public UglyWoman() {
		this.kindWoman = new Beauty();
	}

	// 她可以是KindWomam的任何一个女人的代理,只要你是这一类型
	public UglyWoman(KindWoman kindWoman) {
		this.kindWoman = kindWoman;
	}

	@Override
	public void happyWithMan() {
		this.kindWoman.happyWithMan();// 找人代理
	}

	@Override
	public void makeEyesWithMan() {
		this.kindWoman.makeEyesWithMan();// 找人代理
	}
}

 

 客户端代码

	public static void main(String[] args) {
		KindWoman woman = new UglyWoman();
		woman.makeEyesWithMan();
		woman.happyWithMan();
	}

 

处理延时加载

将代理类进行改造

public class UglyWoman implements KindWoman {

	private KindWoman kindWoman;

	public UglyWoman() {
		this.kindWoman = new Beauty();
	}

	// 她可以是KindWomam的任何一个女人的代理,只要你是这一类型
	public UglyWoman(KindWoman kindWoman) {
		this.kindWoman = kindWoman;
	}

	@Override
	public void happyWithMan() {
		if (kindWoman == null) {
			kindWoman = new Beauty();
		}
		this.kindWoman.happyWithMan();// 找人代理
	}

	@Override
	public void makeEyesWithMan() {
		if (kindWoman == null) {
			kindWoman = new Beauty();
		}
		this.kindWoman.makeEyesWithMan();// 找人代理
	}
}

 

public class Beauty implements KindWoman {

	//加入时间检测
	public Beauty() {
		try {
			Thread.sleep(3000);
			System.out.println("准备");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void happyWithMan() {
		System.out.println("游戏...");
	}

	@Override
	public void makeEyesWithMan() {
		System.out.println("抛媚眼...");
	}
}

 

客户端调用

		long currentTimeMillis = System.currentTimeMillis();
		
		KindWoman woman = new UglyWoman(null);
		
		long currentTimeMillis2 = System.currentTimeMillis();
		System.out.println(currentTimeMillis2 - currentTimeMillis);

		woman.makeEyesWithMan();//在调用具体的方法时,new一个新的对象
		woman.happyWithMan();

 

 

输出结果:

0       -- 休眠3秒,输出“准备”
准备
抛媚眼...
游戏...

 

 

提供额外的功能:AOP 动态代理

public interface Dog {

	public void info();

	public void run();
}

 

public class GunDog implements Dog {

	@Override
	public void info() {
		System.out.println("我是一只猎狗");
	}

	@Override
	public void run() {
		System.out.println("我奔跑迅速");
	}
}

 

 需要切入的代码

public class TxUtil {

	public void beginTx() {
		System.out.println("===模拟开始事务====");
	}

	public void endTx() {
		System.out.println("===模拟结束事务====");
	}

}

 

代理类

public class MyInvokationHandler implements InvocationHandler {
	//需要被代理的对象
	private Object target;

	public void setTarget(Object target) {
		this.target = target;
	}

	//执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		TxUtil tx = new TxUtil();
		tx.beginTx();

		Object result = method.invoke(target, args);
		tx.endTx();

		return result;
	}
}

  

/**
 * 为指定的target生成动态代理实例
 * 
 */
public class MyProxyFactory {

	public static Object getProxy(Object target) {

		MyInvokationHandler handler = new MyInvokationHandler();

		handler.setTarget(target);

		// 创建并返回一个动态代理
		return Proxy.newProxyInstance(target.getClass().getClassLoader(),
				target.getClass().getInterfaces(), handler);

	}
}

 

客户端调用类

 

 
	public static void main(String[] args) {
		Dog target = new GunDog();

		Dog dog = (Dog) MyProxyFactory.getProxy(target);
		dog.info();
		dog.run();
	}

 

输出结果:

===模拟开始事务====
我是一只猎狗
===模拟结束事务====
===模拟开始事务====
我奔跑迅速
===模拟结束事务====

 

这种动态代理在AOP(面向切面编程)里被称为AOP代理,AOP代理可代理目标对象,包含了目标对象的全部方法,并且可以在执行目标方法之前、之后插入一些通用处理。

 

Spring所创建的AOP代理就是这种动态代理,通过配置文件来决定invoke()方法中需要调用哪些拦截器。

当程序需要为目标对象扩展新功能时,无需改变java代理,在配置文件中添加更多的拦截器配置即可。

 

代理模式的优势及使用场景:

客户端代码不能或者不想直接访问被调用对象:比如,创建系统开销很大的对象(延时加载),或者被调用的对象在远程主机上,或者目标对象的功能不能满足需求,这时候就需要创建一个代理对象,返回给客户端使用。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics