前几天听同事说了有个代理模式,但是以前我基本不怎么了解,然后就抽时间去看了看,下面是我看后总结
代理模式就是使用代理对象来操作目标对象,并在代理对象中进行扩展(开闭原则:对扩展开放,对修改关闭)的一种设计模式,
例子:
上大学时,学校内的网络是一个局域网,想上网就得花钱开通账号,虽然不多,但是更想免费用啊,后来在百度上查到这么一个东西;然后在学校找了个服务器,我把自己电脑通过连接到服务器上,就这样我就可以免费上网了…
再比如说一个我们经常听到的,黄牛党,我们买票买不到时,让他们替代给我们买,我们也可以把它称为代理模式
图示:
实现:
静态代理在使用需要定义接口或者父类,被代理类和代理类同时实现该接口或者继承该父类;
特点:
在每次新增函数时,需要要在接口中添加一个新方法,然后在目标对象中实现这个方法,并且在代理对象中实现相应的代理方法,所以我们可以通过反射来实现动态代理
public interface Internet {
boolean internet();
}
目标类:
public class MyComputer implements Internet {
@Override
public boolean internet() {
// TODO 连接网络
System.out.println("电脑连接网络成功");
return false;
}
}
代理类:
public class ServiceProxy implements Internet {
private Internet mInternet;
public ServiceProxy(Internet mInternet) {
this.mInternet = mInternet;
}
@Override
public boolean internet() {
// TODO 服务器连接网络,服务器与客户端建立连接,这样客户端就可以通过代理来访问网络了
// 在代理对象中执行目标对象的方法,告诉目标对象他想做的事情,我已经给他做好了
mInternet.internet();
return false;
}
}
测试类:
public class ProxyTest {
public static void main(String[] args) {
// 目标对象
MyComputer computer = new MyComputer();
// 代理对象,将目标对象传给代理对象,建立代理关系
ServiceProxy serviceProxy = new ServiceProxy(computer);
// 执行代理函数
serviceProxy.internet();
}
}
通过Api中的
Proxy
,InvocationHandler
类实现动态代理,它们的原理就是反射
在反射中我们可以通过对象或Class,通过Class对象获取到它中的所有函数,然后根据Method就可以调用相对于的函数了,如果有兴趣可以自己去看看它们的源码
需要实现的接口:
public interface Internet {
boolean internet();
}
目标对象实现接口
public class MyComputer implements Internet {
@Override
public boolean internet() {
// TODO 连接网络
System.out.println("电脑连接网络成功");
return false;
}
}
测试类:通过Proxy和InvocationHandler实现动态代理;
public class ProxyTest {
public static void main(String[] args) {
Internet mInternet = new MyComputer();
Internet aInternet = (Internet) Proxy.newProxyInstance(mInternet.getClass().getClassLoader(),
mInternet.getClass().getInterfaces(), new InvocationHandler() {
// 回调方法 拦截到目标对象的时候执行
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (proxy instanceof Internet) {
System.out.println("true");
} else {
System.out.println("false");
}
// 通过method.invoke(Object object,Object[] args)调用object中的对应的函数,args是参数
return method.invoke(mInternet, args);
}
});
aInternet.internet();
}
}
当然了,我们还可以定义一个代理类实现InvocationHandler,在该类中实现事件回调处理.代码就不写了
使用动态代理可以更好的对代理者和被代理者进行解耦.
引用android源码设计模式解析与实战中一段话:
代理从适用范围来区分可以分为: