java中的代理模式是一个很重要的模式很多地方都用到,比如Spring框架中。Android中也是比如adil中,比如现在非常流行的网络框架retrofit中等等很多地方都会用到。所以理解代理模式是非常重要的。今天就来谈一下代理模式。
代理顾名思义就是代表另一个事物完成一些工作。也可以理解为中介。举个例子:链家买房子。大家都知道链家是卖房子的中介,它可以卖很多楼盘的房子。比如水岸连城和香格里两个小区。链家作为中介卖这两家的房子,买主不直接和房产商联系,通过链家来买房。
下面我们先用代码来实现一个代理模式:
首先 水岸连城和香格里两个小区嗾使楼盘,所以他们有一些共同的属性 来一个接口:
package com.chs.proxytext;
/**
* 作者:chs on 2016/8/11 16:02
* 邮箱:657083984@qq.com
* 楼盘
*/
public interface LouPan {
/**
* 楼盘的名字
*/
public void getName();
/**
* 楼的价格
*/
public void getPrice();
}
然后 水岸连城 和
香格里 分别 实现了这个接口
package com.chs.proxytext;
import android.util.Log;
/**
* 作者:chs on 2016/8/11 16:07
* 邮箱:657083984@qq.com
* 水岸连城
*/
public class ShuiAn implements LouPan {
@Override
public void getName() {
Log.i("name","水岸连城");
}
@Override
public void getPrice() {
Log.i("ShuiAn_price","5000");
}
}
package com.chs.proxytext;
import android.util.Log;
/**
* 作者:chs on 2016/8/11 16:08
* 邮箱:657083984@qq.com
* 香格里
*/
public class XiangGe implements LouPan {
@Override
public void getName() {
Log.i("name","香格里");
}
@Override
public void getPrice() {
Log.i("XiangGe_price","3000");
}
}
然后是链家 链家的构造里面传入一个楼盘。也就是代理要持有被代理者的对象
package com.chs.proxytext;
import android.util.Log;
/**
* 作者:chs on 2016/8/11 16:09
* 邮箱:657083984@qq.com
* 链家
*/
public class LianJIa implements LouPan {
private LouPan louPan;
public LianJIa(LouPan louPan) {
this.louPan = louPan;
}
@Override
public void getName() {
louPan.getName();
}
@Override
public void getPrice() {
louPan.getPrice();
}
}
最后是main中:
package com.chs.proxytext;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LianJIa lianJIa;
ShuiAn shuiAn = new ShuiAn();
lianJIa = new LianJIa(shuiAn);
lianJIa.getName();
lianJIa.getPrice();
XiangGe xiangGe = new XiangGe();
lianJIa = new LianJIa(xiangGe);
lianJIa.getName();
lianJIa.getPrice();
}
}
运行结果:
08-11 16:37:19.074 3558-3558/com.chs.proxytext I/name: 水岸连城
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/ShuiAn_price: 5000
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/name: 香格里
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/XiangGe_price: 3000
这样以后再有别的楼盘需要链家代理卖,就可以实现LouPan的接口后把自己给链家就可以了。
java中也提供了动态代理的类供我们用,使用起来很简单,首先实现InvocationHandler.
package com.chs.proxytext;
import android.util.Log;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 作者:chs on 2016/8/11 16:46
* 邮箱:657083984@qq.com
* 楼盘handler
*/
public class LouPanHandler implements InvocationHandler {
/**
* 这个就是我们要代理的真实对象
*/
private Object subject;
/**
* 构造方法,给我们要代理的真实对象赋初值
*
* @param subject
*/
public LouPanHandler(Object subject)
{
this.subject = subject;
}
/**
*
* @param proxy 代理类实例
* @param method 被调用的方法对象
* @param objects 调用参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
//在执行代理对象之前可以做一些别的事情
Log.i("执行之前","执行之前做点事情");
Object res = method.invoke(subject, objects);
Log.i("执行之后","执行之后做点事情");
return res;
}
}
main中:
package com.chs.proxytext;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LianJIa lianJIa;
// ShuiAn shuiAn = new ShuiAn();
// lianJIa = new LianJIa(shuiAn);
// lianJIa.getName();
// lianJIa.getPrice();
//
// XiangGe xiangGe = new XiangGe();
// lianJIa = new LianJIa(xiangGe);
// lianJIa.getName();
// lianJIa.getPrice();
LouPan louPanReal = new ShuiAn();
InvocationHandler handler = new LouPanHandler(louPanReal);
ClassLoader classLoader = louPanReal.getClass().getClassLoader();
Class[] interfaces = louPanReal.getClass().getInterfaces();
//获取代理的对象
LouPan louPan = (LouPan) Proxy.newProxyInstance(classLoader,interfaces,handler);
louPan.getName();
louPan.getPrice();
}
}
这里我们将真实的对象传入handler 通过Proxy.newProxyInstance动态生成代理的对象。之后执行代理对象中的方法。
执行结果:
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之前: 执行之前做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/name: 水岸连城
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之后: 执行之后做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之前: 执行之前做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/ShuiAn_price: 5000
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之后: 执行之后做点事情
通过打印的log可以看到 ,当代理对象执行其方法的时候,会跳到handler中通过invoke来执行真实对象中的真实方法。