代理这个词并不陌生,就像当前比较火的游戏英雄联盟,也是由腾讯代理拳头公司的游戏,他负责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方法的主要作用是将对象与代理类进行绑定。