一.概述
例如A要租房,为了省麻烦A会去找中介,中介会替代A去筛选房子,A坐享中介筛选的结果,并且交房租也是交给中介,这就是一个典型的日常生活中代理模式的应用.主要是分为静态代理和动态代理
代理模式的组成:
Abstract Subject:抽象主题-声明真实主题和代理主题共同的接口
Real Subject:真实主题-真实的对象,需要被代理主题引用
Proxy Subject:代理主题-因为ProxySubject引用了RealSubject,并且实现了跟RealSubject一样的接口,所以ProxySubject可以操作 RealSubject,还可以提供一些附加操作,例如before & after
代理模式的优缺点:
优点:
1.代理作为调用着和真实对象的中间层,降低了模块间和系统的耦合性
2.可以以一个小对象代理一个大对象,达到优化系统提高运行速度的目的
3.提供RealSubject的权限管理
4.容易扩展,RealSubject和ProxySubject都接口化了,RealSubject更改业务后只要接口不变,ProxySubject可以不做任何修改.
缺点:
1.同优点1,因为调用者和真实对象多了一个中间层,所以会增加调用响应的时间
二:实现
拿A找中介租房为Demo来构建代理模式.
1.静态代理
根据场景先定义一个抽象主题,IHouse,提供三个方法,分别是获取房屋信息,签合同和付租金.
public interface IHouse {
void getInfo();
void signContcart();
void payMoney();
}
接下来定义真实主题,并实现IHouse接口.增加房屋名称和价格两个属性,填充借口方法,在获取房屋信息的时候就把房屋名称打印出来;签合同的时候log签合同,付租金的时候log付租金.
public class House implements IHouse{
private String name;
public House(String name) {
this.name = name;
}
@Override
public void getInfo() {
System.out.println("====getInfo==="+name);
}
@Override
public void signContcart() {
System.out.println("====signContcart==="+"签合同");
}
@Override
public void payMoney() {
System.out.println("====payMoney==="+"付租金");
}
定义房屋代理,同样需要实现IHouse接口,并持有House的引用.可以看到代理类其实就像有封装House,提供了一些附加操作,例如客户要看房子的时候代理会先检索自己库存的房屋信息,签合同之前要准备合同之类的
public class ProxyHouse implements IHouse{
private IHouse iHouse;
public ProxyHouse(IHouse iHouse) {
this.iHouse = iHouse;
}
@Override
public void getInfo() {
iHouse.getInfo();
}
@Override
public void signContcart() {
iHouse.signContcart();
}
@Override
public void payMoney() {
iHouse.payMoney();
}
对于客户来说,完全不用跟House进行直接交互,这里先定义一个房子叫薰衣草庄园,建立一个房屋代理,把唐顿庄园委托给代理.客户要找房子,签合同,付租金直接找代理就行了.
IHouse iHouse=new House("薰衣草庄园");
IHouse proxyhouse=new ProxyHouse(iHouse);
Log.i("=====", "looking for a perfect house");
proxyhouse.getInfo();
proxyhouse.signContcart();
proxyhouse.payMoney();
System.out.println("====="+"so easy");
效果如下:
2.动态代理
上面介绍的都是自己先写好的代理类,这样代理关系都是固定的,当代理多个真实对象的时候就要写多个代理类,并且会产生冗余的代码,扩展性和可维护性都不高,而动态代理是基于反射实现了在程序运行的过程中才决定代理什么对象.像AOP的核心思想就是动态代理.(这里使用的是Java的动态代理)
这里写一个ProxyHandler实现InvocationHandler的invoke接口,下面上代码进行演示
public class ProxyHandler implements InvocationHandler{
Object obj;
public ProxyHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object ret= method.invoke(obj,objects);
return ret;
}
}
在MainActivity中
IHouse iHouse=new House("摩尔庄园");
ProxyHandler house= new ProxyHandler(iHouse);
IHouse iHouse1= (IHouse) Proxy.newProxyInstance(iHouse.getClass().getClassLoader(),iHouse.getClass().getInterfaces(),house);
iHouse1.getInfo();
iHouse1.signContcart();
iHouse1.payMoney();
从结果可以看出在真正invoke真实对象的方法之前都会打印出方法,也可以在这里做一些其他的对象控制.
三:总结
学习设计模式其实最适合的方法就是拿来用,在适用于该模式的场景下灵活得去运用它才算是真正的掌握一种模式.