代理模式 静态代理到动态代理
代理模式这种设计模式是一种使用代理对象来执行目标对象的方法并在代理对象中增强目标对象方法的一种设计模式。代理对象代为执行目标对象的方法,并在此基础上进行相应的扩展。
- 代理模式的元素是:共同接口、代理对象、目标对象。
- 代理模式的行为:由代理对象执行目标对象的方法、由代理对象扩展目标对象的方法。
-
代理模式的宏观特性:对客户端只暴露出接口,不暴露它以下的架构。
我们按照这个套路写一下,比如我们程序猿,每次都是PM去接需求,然后把活丢给我们,CTO只知道把需求给产品,看到了PM产品做到好,但是没看到我们辛苦写代码啊....
写一个代码接口
/**
* @author Administrator
* @time 2018/10/18 14:30
* @describe 会写代码的接口
*/
public interface WriteCode {
//内部方法写代码
void doWriteCode();
}
程序猿实现了写代码接口,每天PHP是最好的语言...
public class CodeMnkey implements WriteCode {
private static final String TAG = "LeoCode";
@Override
public void doWriteCode() {
Log.e(TAG, "CodeMnkey Writ eCode: PHP is the best language in the world ");
}
}
产品经理接口,大家看着产品经理啥都能干,其实都是我们干的
public class ProductManager implements WriteCode {
private CodeMnkey writeCode;
private static final String TAG = "LeoCode";
public ProductManager(CodeMnkey writeCode) {
this.writeCode = writeCode;
}
/**
* @author Administrator
* @time 2018/10/18 14:35
* @describe 调用产品经理写代码功能
*/
@Override
public void doWriteCode() {
Log.e(TAG, "产品经理下发任务: 根据手机壳颜色改变APP主题");
writeCode.doWriteCode();
}
}
产品经理接需求
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建产品经理
ProductManager productManager = new ProductManager(new CodeMnkey());
//产品经理接活
productManager.doWriteCode();
}
}
产品经理看起来一个人就完成了任务...
但是静态代理有个很严重的缺点,就是比如我们的写代码接口多了一个加工资方法,那么我们的程序猿和产品经理都得去更新去实现这个方法。我们加了一个加工资方法,可见程序猿和产品经理都发生了爆红。
Java有独特的反射技术,可以实现动态代理。
举个中介的例子
房子拥有出租和收费俩方法
/**
* @author Administrator
* @time 2018/10/18 15:39
* @describe 出租房子接口
*/
public interface RentalHousing {
void lease();
void CollectMoney();
}
这是房东,房东要出租房子和收钱
/**
* @author Administrator
* @time 2018/10/18 15:38
* @describe 房东
*/
public class Homeowner implements RentalHousing {
private static final String TAG = "LeoCode";
@Override
public void lease() {
Log.e(TAG, " 房东 :出租房屋 ");
}
@Override
public void CollectMoney() {
Log.e(TAG, "房东 :收到房钱");
}
}
中介代理,拿到房东钥匙,如果该收房费,就扣中介费
其实这里代码 invoke 就是最简单的方法反射。
/**
* @author Administrator
* @time 2018/10/18 15:38
* @describe 房屋中介
*/
public class Intermediary implements InvocationHandler {
private static final String TAG = "LeoCode";
private Object object;
//持有传入的对象,中介有可能要对接N个客人
public Intermediary(Object object) {
this.object = object;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//如果是收钱,就扣点中介费
if (method.getName().equals("CollectMoney")) {
Log.e(TAG, "中介 :该给房东收钱了, 收到钱,我先拿一部分中介 ");
}
method.invoke(object, objects);
return null;
}
}
测试一下
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//房主
Homeowner homeowner = new Homeowner();
//房主找到了中介
Intermediary intermediary = new Intermediary(homeowner);
//成功调用了方法反射出来出租房子接口
RentalHousing homeownerProxy = (RentalHousing) Proxy.newProxyInstance(intermediary.getClass().getClassLoader(), homeowner.getClass().getInterfaces(), intermediary);
//中介出租房子
homeownerProxy.lease();
//中介收钱
homeownerProxy.CollectMoney();
}
}
Log打印
image.png
有人说Proxy.newProxyInstance();这个方法到底是啥?
API: http://www.cjsdn.net/Doc/JDK60/java/lang/reflect/Proxy.html
三个参数,第一个代理类的ClassLoader,第二个要代理的接口,第三个实现代理的对象
现在我们去变更下租房接口,添加一个收回房子方法。
房主实现方法
我们发现我们中介可以直接调用方法
动态代理最大的好处就是代理者比较省代码,而且在调用被代理的对象的方法前后可以做任意事情,也不用担心因为接口变动,自己也得跟着接口去变动,这是动态代理最大的优势,这篇文章到此为止,在Android的IPC夸进程通信其实底层也是动态代理在运转。