java代理模式之静态代理与动态代理


代理这个词并不陌生,就像当前比较火的游戏英雄联盟,也是由腾讯代理拳头公司的游戏,他负责lpl赛区所有的赛事游戏更新以及捞油水的法子。java中的代理模式与这略微有些不同,因为他与赚钱无关,哈哈哈。只是帮助理解,下面说一个比较浅显的例子。

在公司中有前台与公司其他成员,公司其他成员难免会有快递啊、或者老婆来访查堂什么的。但是公司明确规定,上班期间不能做与上班无关的事情,因此无法查收快递、老婆查堂没办法去见。因此这些事都交给前台全权代理。下面用代码实现这一逻辑。

1.静态代理模式

首先定义一个员工接口,如下IWorker

public interface IWorker {
	/**
	 * 收快递
	 */
	void receiveKuaiDi();
	/**
	 * 见来访者
	 */
	void viewVistor();
}

再定义程序员Coder类,实现Iworker接口:

public class Coder implements IWorker{
<span style="white-space:pre">	</span>
	@Override
	public void receiveKuaiDi() {
		System.out.println("程序员收了快递");
		
	}

	@Override
	public void viewVistor() {
		System.out.println("程序员见他的来访者");
		
	}

}
再定义一个经理类Manager,实现IWorker接口:

public class Manager implements IWorker{

	@Override
	public void receiveKuaiDi() {
		System.out.println("经理收取了快递");
		
	}

	@Override
	public void viewVistor() {
		System.out.println("经理见他的来访者");
		
	}
}
/**
 * 经理的前台代理
 * @author Administrator
 *
 */
public class ManagerProxy implements IWorker{
<span style="white-space:pre">	</span>private Manager manager;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>public ManagerProxy(){
<span style="white-space:pre">		</span>if (manager==null) {
<span style="white-space:pre">			</span>manager=new Manager();
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void receiveKuaiDi() {
<span style="white-space:pre">		</span>manager.receiveKuaiDi();
<span style="white-space:pre">		</span>
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void viewVistor() {
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>manager.viewVistor();
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>


}
</pre><pre name="code" class="java">/**
 * 程序员前台代理
 * @author Administrator
 *
 */
public class CoderProxy implements IWorker{
<span style="white-space:pre">	</span>private Coder coder;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>public CoderProxy(){
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>if (coder==null) {
<span style="white-space:pre">			</span>coder=new Coder();
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void receiveKuaiDi() {
<span style="white-space:pre">		</span>coder.receiveKuaiDi();
<span style="white-space:pre">		</span>
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void viewVistor() {
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>coder.viewVistor();
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>


}
</pre><pre name="code" class="java">public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ManagerProxy managerProxy = new ManagerProxy();
<span style="white-space:pre">		</span>managerProxy.receiveKuaiDi();
<span style="white-space:pre">		</span>managerProxy.viewVistor();
<span style="white-space:pre">		</span>System.out.println("=-----------------------");
<span style="white-space:pre">		</span>CoderProxy coderProxy = new CoderProxy();
<span style="white-space:pre">		</span>coderProxy.receiveKuaiDi();
<span style="white-space:pre">		</span>coderProxy.viewVistor();
	}

}


输出结果如下,

以上一个对象对应一个代理前台,及其的浪费钱人力。虽然实现了基本的代理模式,但是你会发现,程序的扩展性非常不好。在需要代理的类

增多时,需要定义更多的代理类,随后就有了以下的静态代理模式的升华版:

修改代理类如下:

/**
 * 所有前台代理
 * @author Administrator
 *
 */
public class ReceptionProxy implements IWorker{
	private IWorker worker;
	
	public ReceptionProxy(IWorker worker){
		this.worker=worker;
	}
	@Override
	public void receiveKuaiDi() {
		worker.receiveKuaiDi();
		
	}

	@Override
	public void viewVistor() {
		
		worker.viewVistor();
	}
}

  测试代码就不贴了,这里可以看到,这次公司就不需要为每个员工招一个代理前台了,只需要一个前台就够了。快递到来、或者有人来访就只需要前台代替对应的人进行处理。这利用了java的多态属性实现。

2.动态代理:

还是这个例子,贴代码说明。

动态代理模式的代理类如下;

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


/**
 * 前台代理
 * @author Administrator
 *
 */
public class ReceptionProxy implements InvocationHandler{
	private Object targetObject;
	@Override
	/**
	 * method是调用的方法,即需要执行的方法;args是方法的参数;
	 * 根据方法名,调用对应对象中的方法
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object ret=null;
		try {  
            System.out.println("方法调用前……");  
            //调用目标方法  
            /**
             * targetObject 方法所属的类
             * args 方法的参数
             */
            ret = method.invoke(targetObject, args);  //调用targetObject 中对应的方法
            System.out.println("方法调用完后……");  
        } catch (Exception e) {  
            e.printStackTrace();  
            System.out.println("error-->>" + method.getName());  
            throw e;  
        }  
		return ret;
	}
	
	/**
	 * 返回接口类型
	 * @param target
	 * @return
	 */
	public Object newProxyInstance(Object target){
		this.targetObject=target;
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}

	

}
测试代码:

public class test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ReceptionProxy proxy=new ReceptionProxy();
		Coder coder=new Coder();
		IWorker worker=(IWorker) proxy.newProxyInstance(coder);
		worker.receiveKuaiDi();
		worker.viewVistor();
	}

}

相比较于静态代理升华版之后的优势在于,代理类不关心什么方法,即使员工接口中新增了方法,代理类仍不需要做任何的改变便可实现代理,只需要修改realSubject,与abstractSubject代码即可。实现了高度的解耦。在动态代理模式中,代理类需要实现InvocationHandler,并且实现其invoke方法,invoke方法的作用主要是根据传入的对象调用其对应接口方法。newInstance方法的主要作用是将对象与代理类进行绑定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值