彻底明白Android设计模式—(动态)代理模式
代理模式和动态代理模式
代理模式其实就是提供了对目标对象的另外的访问方式,通过代理对象访问目标对象 为啥要这么麻烦呢!!!其实是为了不去修改原有的代码,通过代理也可以访问这个对象而且可以进行扩展
这种模式有什么应用场景呢?先说下生活中对应的场景,明星接通告一般商家要找明星做活动,是要先找到他的经纪人,然后经纪人去负责一些琐碎的或者运营方面的事情,而明星只需要做具体的活动相关事情就可以了。这里经纪人的作用就是作为了一个代理。
静态代理
首先是静态代理,上代码
/**
* 首先声明一个接口,用于工作的接口
*/
public interface IStarDao {
void dowork();
}
/**
* 明星工作类
* 主要为演戏
*/
public class SuperStarDao implements IStarDao {
@Override
public void dowork() {
//演戏工作
}
}
/**
* 经纪人代理类
* 主要是负责接活,并且安排明星工作,以及后续宣传工作
*/
public class StarbrokerDaoProxy implements IStarDao {
private IStarDao starDao;
public StarbrokerDaoProxy(IStarDao starDao) {
this.starDao = starDao;
}
@Override
public void dowork() {
/*--接活--*/
starDao.dowork();//明星工作
/*--宣传工作--*/
}
}
ok,至此明星和经纪人已经创建完毕,接下来就是怎么去操作,首先找到具体的明星,然后找到对应的经纪人,也就是代理类,从而完成所有工作
public void main() {
SuperStarDao starDao = new SuperStarDao();
StarbrokerDaoProxy proxy = new StarbrokerDaoProxy(starDao);
proxy.dowork();
}
动态代理
动态代理的特点是不需要提前创建代理对象,而是利用反射机制在运行时创建代理类,从而动态实现代理功能 也就是说,这里的明星不需要具体的经纪人了。有活动的时候,可以创建一个经纪人,可以是自己,可以是家人,然后完成原本代理的一些工作,见代码
public void main() {
final IStarDao starDao = new SuperStarDao();
IStarDao proxy = (IStarDao) Proxy.newProxyInstance(
starDao.getClass().getClassLoader(),
starDao.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*--接活--*/
Object returnValue = method.invoke(starDao, args);//明星工作
/*--宣传工作--*/
return returnValue;
}
});
proxy.dowork();
}
在Android中的应用
Retrofit,想必大家都很熟悉,retrofit其实核心内容就是用了动态代理。
想想retrofit是怎么工作的?在interface里面写上需要配置的请求方法,并添加一些注解 然后创建出interface的实例,就可以直接调用方法进行网络请求了。看看代码:
public interface ApiService {
@POST(RetrofitHelper.APP_V1 + "/banner")
Observable<BaseEntity<List<Banner>>> getBanners();
}
ApiService mService = new Retrofit.Builder().baseUrl("").build().create(ApiService.class);
service.getBanners().enqueue(callback);
我们只是写了ApiService接口和接口下面的getBanners方法,然后就可以进行网络请求。所以retrofit是代替我们写了网络请求的具体逻辑,也就是完成了代理的这样一个作用。
具体怎么代理的呢?奥秘主要就在这个***.create(ApiService.class)方法***里面,看看源码:
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
看到这个newProxyInstance方法了吧,这就是创建动态代理类的方法。invoke方法里面就是具体去拆解 接口里面方法的一些参数,然后完成网络请求的整个过程了,也就是代理帮你做的一些事情。
这里顺便就简单说下这些源码干了什么事,也方便大家自己研究源码
- loadServiceMethod 主要是读取接口里面每个方法的注解啊,参数啊等等
- new OkHttpCall 主要是调用okhttp的一些方法,发起一些网络请求
- adapt(okHttpCall) 主要是转换OkHttpCall对象,并且切换到主线程
- 温故而知新:设计模式之Builder
- 温故而知新:设计模式之单件模式(Singleton)
- sudo命令使用的几个场景
- .NET Core系列 : 2 、project.json 这葫芦里卖的什么药
- 关闭与恢复visual studio实时调试器
- linux系统下的权限知识梳理
- c#如何启动/干掉/查找 进程
- Android中Application的应用
- 孟昭莉博士:大数据大道之行
- .NET Core系列 :3 、使用多个项目
- 完整部署CentOS7.2+OpenStack+kvm 云平台环境(2)--云硬盘等后续配置
- 完整部署CentOS7.2+OpenStack+kvm 云平台环境(3)--为虚拟机指定固定ip
- ubuntu系统升级记录
- .NET Core系列 :4 测试
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 必要掌握!Window、WindowManager !
- 面试必备:ThreadLocal+Looper+Handler
- 子线程 真的不能更新UI ?
- Web前端开发 HTML设计 经验与技巧总结
- [OHIF-Viewers]医疗数字阅片-医学影像-辅助工具-Redux DevTools-DevTools for Redux with hot reloading, action replay,
- 全面理解:Android中的线程及线程池
- Ubuntu系统 安装与配置 常见异常与解决办法
- [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中二-Redux&react-redux状态管理详解
- Bitmap的加载和Cache
- Python全栈 Linux基础之2.Linux终端命令简介
- Ubuntu系统 使用与开发 常见异常与解决办法
- 淘宝首页Bug!嵌套滑动及NestedScroll
- 曝光埋点方案:recyclerView中的item曝光逻辑实现
- Android中的动画全解!
- Python 爬取留言板留言(二):多线程版+selenium模拟