Android中的代理模式
Android中的代理模式
1. 什么是代理
比如我们生活中的找出租屋,需要去找中介进行寻找挑选.而这里的中介就是代理.列子中看出代理特点如下1. 租客跟中介要做成的最终目的是一致的就是租到房子(目标一致).2. 中介资源多,有权利跟房东进行价格协商(功能强大).3. 中介是不会让我们直接跟房东进行协商(无法直接访问到目标). 我们在开发中也是有相似的情况出现你有个a类,本来是调用c类方法,完成某个功能.但是c类不让a直接调用.a-->不能直接调用c的方法在a和c之间直接创建一个b代理类,c让b访问.a-->访问b方法-->访问c方法
总结:我们在开发中使用代理模式是为了在不修改目标对象的基础上,增强主业务逻辑,客户类真正的想要访问的对象是目标对象,但是客户类真正可以访问的对象是代理对象.
2. 代理模式的作用
1.功能增强:在原有的功能上,增加额外的功能.
2.控制访问:代理类不让你访问到目标类.
3. 实现代理的方式-静态代理
1.自己手工实现的代理类.
2.代理的目标类是固定的.
特点:实现简单,容易理解.
举例子:
用户买鞋子行为
用户(客户端)-----商家(代理类)-----厂家(目标类)
其中,商家和厂家都是卖鞋子的,他们的完成的功能是一致的都是卖鞋子
interface IShoesSell {//num 购买的数量 返回值是一双鞋子的价格public float sell(int num);}//特步厂家public class TebuShoesSellimpl implements IShoesSell {@Overridepublic float sell(int num) {return 300.0f;}}//京东商家public class JD implements IShoesSell {private IShoesSell mFactory = new TebuShoesSellimpl();@Overridepublic float sell(int num) {float price = mFactory.sell(num);price += 25;return price;}}public void main(String[] args) {//创建代理对象-JD 进行购买JD jd =new JD();jd.sell(1); //这里我们就是通过京东购买了特步的鞋子325块}
我们可以在JD类sell方法进行功能增强(添加优惠券,满减等),也不难发现我们JD类里面的目标类是固定的(特步厂家TebuShoesSellimpl).
多添加厂家和商家代码的情况:
//京东商家public class JD implements IShoesSell {private IShoesSell mFactory = new TebuShoesSellimpl();@Overridepublic float sell(int num) {float price = mFactory.sell(num);price += 25;return price;}}//拼多多商家public class PDD implements IShoesSell {private IShoesSell mFactory = new TebuShoesSellimpl();@Overridepublic float sell(int num) {float price = mFactory.sell(num);price -= 25;return price;}}//安踏厂家public class AntaShoesSellimpl implements IShoesSell {@Overridepublic float sell(int num) {return 350.0f;}}//京东商家-安踏public class JDAnta implements IShoesSell {private IShoesSell mFactory = new AntaShoesSellimpl();@Overridepublic float sell(int num) {float price = mFactory.sell(num);price += 25;return price;}}//拼多多商家-安踏public class PDDAnta implements IShoesSell {private IShoesSell mFactory = new AntaShoesSellimpl();@Overridepublic float sell(int num) {float price = mFactory.sell(num);price -= 25;return price;}}//这里就带来一个问题我只要添加一个目标类(安踏厂家),那我的代理类(商家)都要对应添加类,会出现一对n的变化,增加代码维护成本.
缺点:
- 目标类增多对应的代理类成倍增加.
- 当接口的方法进行添加修改时,会影响到众多类实现类需要修改,大大增加出错率.
4. 实现代理的方式-动态代理
优点:
- 代理类数量可以很少.
- 当你修改了接口中的方法时,不会影响代理类.
概念:
在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态的制定要代理目标类.
理解:
正常我们在java中想要创建对象是需要两个步骤
- 创建类文件,java文件编译成class文件.
- 使用构造方法new JD() ,创建类的对象.
动态代理直接是第二步骤(创建类的对象),跳过类文件创建.(so 文件少的原因)
动态代理的实现需要掌握的类(java.lang.reflect):
- InvocationHandler:
接口,invoke方法里面填写功能代码
public Object invoke(Object proxy, Method method, Object[] args);
- Method:
类中的方法,通过Method对象就可以执行某个方法. (invoke方法)
public native Object invoke(Object obj, Object ... args)
- Proxy:
核心的对象,主要是创建代理对象.使用newProxyInstance()代替new.
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
实现动态代理完整代码
IShoesSell mFactory = new TebuShoesSellimpl(); //特步厂家
// IShoesSell mFactory = new AntaShoesSellimpl(); //安踏厂家IShoesSell proxy = (IShoesSell)Proxy.newProxyInstance(mFactory.getClass().getClassLoader(), mFactory.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {float price = (float) method.invoke(mFactory, args);price += 30;// 京东代理//price -= 25; 拼多多代理return price;}});proxy.sell(1);
下面是实际的项目中的运用–获取项目中metaData数据进行修改
通过源码发现metadata 在ApplicationInfo中metaData属性.
private static void hookPM( ) {try {//获取ActivityThread对象Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");Field field = activityThreadClass.getDeclaredField("sCurrentActivityThread");field.setAccessible(true);Object activityThread = field.get(null);//获取了PackageManager对象Method getPackageManager = activityThread.getClass().getDeclaredMethod("getPackageManager");getPackageManager.setAccessible(true);Object iPackageManager = getPackageManager.invoke(activityThread);//获取IPackageManager接口的Class对象Class<?> iPackageManagerClass = Class.forName("android.content.pm.IPackageManager");//生成动态代理类Object pmProxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), //加载代理类的类加载器new Class[]{iPackageManagerClass}, //代理类需要实现的接口 (需要实现被代理类的接口)(proxy, method, args) -> { // 当被代理类的接口实现方法被调用时,会回调此实现类的invoke()方法,该方法中应该保证被代理类的原逻辑的执行(即 return时的调用)//ApplicationInfoif (method.getName().equals("getApplicationInfo")) {ApplicationInfo invoke = (ApplicationInfo) method.invoke(iPackageManager, args);if (invoke.metaData == null) {} else {Bundle metaData = invoke.metaData;metaData.putString("BD_KEY", "fdfdfdfffff");metaData.putString("GD_KEY", "fffffsdssss");}return invoke;} else {return method.invoke(iPackageManager, args);}});Field sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager");sPackageManagerField.setAccessible(true);sPackageManagerField.set(activityThread, pmProxy);} catch (Exception e) {e.printStackTrace();}}
5. 总结
Android中的代理模式相关推荐
- Android常见设计模式——代理模式(Proxy Pattern)
文章目录 1. 前言 2. 代理模式(Proxy Pattern) 2.1 静态代理模式 2.2 动态代理模式 3. Android 中的代理模式 3.1 Retrofit中的代理模式(没有被代理者) ...
- Android常见设计模式——代理模式(Proxy Pattern)(二)
文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...
- 轻松学,Java 中的代理模式(proxy)及动态代理
我们先来分析代理这个词. 代理 代理是英文 Proxy 翻译过来的.我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了. 她们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人. 按理说,顾客 ...
- Android中Activity启动模式
Android中Activity启动模式一共是四种,这里我写一下我对其的理解: 1.standard(默认) 2.singleTop,如果某个Activity设置了该属性,且当前Activity就是这 ...
- 轻松学,Java 中的代理模式及动态代理
前几天我写了<秒懂,Java 注解 (Annotation)你可以这样学>,因为注解其实算反射技术中的一部分,然后我想了一下,反射技术中还有个常见的概念就是动态代理,于是索性再写一篇关于动 ...
- 「补课」进行时:设计模式(5)——从 LOL 中学习代理模式
1. 前文汇总 「补课」进行时:设计模式系列 2. 从 LOL 中学习代理模式 我是一个很喜欢玩游戏的人,虽然平时玩游戏的时间并不多,但我也是一个忠实的 LOL 的爱好者,就是段位有点惨不忍睹,常年倔 ...
- 第07课:生活中的代理模式——帮我拿一下快递
用程序来模拟生活 从剧情中思考代理模式 代理模式的模型抽象 代码框架 类图 基于框架的实现 模型说明 代理模式的优点 代理模式的缺点 应用场景 [故事剧情] 八月中秋已过,冬天急速飞来--一场秋雨一场 ...
- android中的recovery模式
这里使用基于freescale的imx_r9.2 patch的android源码分析. android中的recovery模式,作为android的开发者或者用户都应该清楚和了解.android利用r ...
- Spring中的代理模式
Spring中的代理模式,是Spring中一大核心 AOP(切面编程)的底层实现. 代理模式可分为: 静态代理 动态代理 静态代理 涉及三类角色,简单分析一下: 抽象角色(一般会使用接口或抽象类解决) ...
最新文章
- 技术的那些事儿_3_西方技术管理的精髓
- SQL_Server2008数据连接池
- Redis是如何写代码注释的?
- 分布式机器学习_京东出来的java工程师,竟然不知道分布式、高并发、多线程的区别?...
- php加水印功能,PHP图片加水印功能
- Python之数据重塑——【stack()方法和unstack()方法、pivot()方法】
- 一个问题就可以辨别真假NLP(自然语言处理)研究者
- 正确评估SQL数据库性能,你必须知道的原理和方法!
- 在Jenkins远程链接Linux系统,然后执行shell命令-亲测可用【转】
- 红警 1 游戏开源,代码非常规范,网友:秀色可餐
- php-redis中文参考手册_zset
- csdn 博客添加目录方法
- stata中计算公式命令_Stata:runby - 一切皆可分组计算!
- apriori关联规则
- Linux内存管理宏观篇(五)物理内存:页面分配和释放页面
- 电商产品销售管理后台ui模板
- HYSPLIT简明教程
- Java 拾遗补阙 ----- 浅拷贝和深拷贝(对象克隆)
- 空气负氧离子监测系统建设方案
- 在visio中不借助公式编辑器在字母上方打波浪线
热门文章
- 紧随大数据浪潮:爬虫工具采集同花顺圈子评论教程
- 华为计算机技能,华为P20手机新技能,电脑模式你玩过吗?有了它迅速实现
- arcgis engine 入门难点——什么是接口查询(QueryInterface)
- 组装微型计算机需要哪些硬件设备,组装电脑需要哪些配件
- 2021年度总结 -- 致自己也致你们
- VS2010 英文旗舰版 MFC 生成安装程序报错
- 抓取万方数据内海量论文
- android 解决asset下面文件太大报错问题
- python在一个画布上画多个子图
- Qt:setEnabled()和setClickable()