前言:什么叫设计模式?
设计是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路。通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。我们使用设计模式最终的目的是实现代码的高内聚和低耦合。
代理模式
一、定义
提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。而代理对象在客户端和目标对象之间起到中介作用。
二、类型
(一)静态代理:
静态代理,就是需要我们编写一个代理类来实现我们需要代理的所有方法。
public interface ProxyInterface {
void choiceBetterHouse(); //模拟挑选优质房子
void buyHouse(); //模拟买房子
}
然后我们定义一个叫Petter的人。
public class Petter implements ProxyInterface {
private static final String TAG = Petter.class.getSimpleName();
@Override
public void choiceBetterHouse() {
Log.d(TAG,"挑选优质房子");
}
@Override
public void buyHouse() {
Log.d(TAG,"买房子");
}
}
然后定义代理类。
public class StaticProxy implements ProxyInterface {
private Petter petter;
public StaticProxy(Petter petter) {
this.petter = petter;
}
@Override
public void choiceBetterHouse() {
petter.choiceBetterHouse();
}
@Override
public void buyHouse() {
petter.buyHouse();
}
}
然后调用代理。
Petter petter = new Petter();
StaticProxy agency = new StaticProxy(petter);
agency.choiceBetterHouse();
agency.buyHouse();
就是petter找代理挑选优质房子,买房子。卖家接触的都是中介,真正执行和做决定的是Petter。
(二)动态代理:
动态代理和静态代理的区别就是动态代理不用我们去手动编写代理类。动态代理就是JDK提供的机制,可在内存中动态的生成代理类。
例子还是上面的例子,我们重新编写动态代理类。
public class DynamicProxy implements InvocationHandler {
private static final String TAG = DynamicProxy.class.getSimpleName();
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d(TAG,"invoke");
Object result = method.invoke(object,args);
return result;
}
}
动态代理的核心就是继承InvocationHandler这个接口,通过method的invoke方法来间接调用原本的方法。这里和java反射调用方法的时候一样。
然后我们看客户端是如何调用的。
Petter petter = new Petter();
// 返回一个代理对象
ProxyInterface proxyPetter = (ProxyInterface) Proxy.newProxyInstance(
petter.getClass().getClassLoader(),
petter.getClass().getInterfaces(),
new DynamicProxy(petter));
proxyPetter.choiceBetterHouse();
proxyPetter.buyHouse();
这里就是最关键的一步了,Proxy.newProxyInstance来生成一个代理对象。通过这个代理对象就可以调用需要被代理的方法了。接下来我们来看输出。
01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/DynamicProxy: invoke
01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/Petter: 挑选优质房子
01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/DynamicProxy: invoke
01-23 11:40:14.169 18725-18725/com.yink.designpattern.designpattern D/Petter: 买房子
三、代理模式和装饰模式的区别
(1) 代理模式,侧重于不能直接访问一个对象,只能通过代理来间接访问,比如对象在另外一台机器上,或者对象被持久化了,对象是受保护的。
(2) 装饰模式是因为没法在编译器就确定一个对象的功能,需要运行时动态的给对象添加职责,所以只能把对象的功能拆成一个个的小部分,动态组装。这些功能是由使用者动态配置的。但是代理模式在编译器其实就已经确定了和代理对象的关系。
(3) 这个两个设计模式是为了解决不同的问题而抽象总结出来的。是可以混用的。可以在代理的基础上在加一个装饰,也可以在装饰器的基础上在加一个代理。
有所补充。