浅谈Android源码与设计模式

来源:互联网 发布:python离线安装包下载 编辑:程序博客网 时间:2024/06/15 20:46

七大基本原则
单一职责原则、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、组合/聚合优先原则。


一、单例模式

1、恶汉模式:通过预先创建一个实例化的静态对象的方式实现单例。

缺点:增加了应用加载的时间以及存储对象的资源空间(有实例化的静态对象存在的类,ClassLoader会预先加载此类,即使没有被任何地方调用过)。
优点:第一次getInstance不需要创建对象,运行时获取对象的速度快。
2、懒汉模式:在第一次getInstance方法中实例化静态对象,实现单例。

缺点:需要添加synchronized关键字以实现多线程,每次调用getInstance都要进行同步,耗费不必要的资源。第一次getInstance需要创建对象,运行时获取对象的速度稍慢。
优点:只有使用时才会被实例化,一定程度上节约了资源。
3、双重校验锁模式:通过对实例的双重判空,达到实现单例的目的。


缺点:第一次加载反应稍慢。在高并发时有可能出现失败。
优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高。

4、静态内部类单列模式:getInstance返回静态内部类的静态单例对象。

既实现了线程安全,又延迟了单例的实例化,推荐的单例模式实现方式。


5、安卓中的单例模式
Context中的getSystemServer(String name),返回的系统服务即是单例。

6、实践
管理类(Manager)、工具类(Utils)等都可以实现成单例模式。

7、优缺点

二、建造者模式




1、使用场景
(1)相同的方法,不同的执行顺序,产生不同的事件结果时。
(2)多个部件都可以装配到一个对象中,但是产生的运行结果又不相同时。

2、安卓中的建造者模式
AlertDialog,其中实现链式调用的关键点是每个setter方法都返回自身,也就是return this。



3、实践
为计算机组装硬件——构建主机、设置操作系统、设置显示器等等。

4、优缺点

三、原型模式


1、使用场景
(1)类初始化需要消耗大量资源,如数据、硬件等,可以通过原型拷贝避免消耗。
(2)类初始化需要非常繁琐的数据准备或访问权限。
(3)保护性拷贝。
2、安卓中的原型模式
ArrayList的Clone方法


3、深拷贝与浅拷贝
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

4、实践
用户登录信息的备份与共享。
5、优缺点

四、工厂方法模式


1、使用场景
在任何需要生成复杂对象的地方,都可以使用工厂模式。复杂对象适合使用工厂模式,用new就可以完成创建的对象无序使用工厂模式。

2、安卓中的工厂方法模式
HashSet、ArrayList与Iterator接口之间即是工厂方法模式的关系。



3、实践
安卓中的数据存储类型有:文件、SharedPreference、SQLite,将每一种数据存储操作封装成产品类。


五、抽象工厂模式


1、使用场景
一个对象族有相同的约束时可以使用抽象工厂模式。

2、安卓中的抽象工厂模式
MediaPlayerFactory:MediaPlayerFactory是安卓底层为创建不同MediaPlayer所定义的一个类。


3、实践
例如:自行车产品族、小汽车产品族、大客车产品族

4、优缺点


5、简单(静态)工厂模式、工厂方法模式、抽象工厂模式区别
简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂方法 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)



六、策略模式


1、使用场景
(1)针对同一类型问题的多种处理方式,仅仅是具体行为有差别时。
(2)需要安全地封装多种同一类型的操作时。
(3)出现同一抽象类有多个子类,而又需要使用if-else或者switch-case来选择具体子类时。

2、安卓中的策略模式
TimeInterpolator(时间插值器)

3、实践
地铁站的收费策略系统

4、优缺点


七、状态模式



1、使用场景
(1)一个对象的行为取决于太多状态,并且它必须在运行时根据状态改变它的行为。
(2)代码中包含大量与对象状态的条件语句,例如,一个操作中含有庞大的多分支语句(if-else或switch-case),且这些分支依赖于该对象的状态。

2、安卓中的状态模式
Wifi的状态管理(蓝牙、MediaPlayer等含有状态机的都一样)


3、实践
用户登录状态系统
4、优缺点


八、责任链模式


1、使用场景
(1)多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定。
(2)在请求处理者不明确的情况下向多个对象中的一个提交下一个请求。
(3)需要动态指定一组对象处理请求。

2、安卓中的责任链模式
Touch事件分发机制,根据onTouchEvent方法返回值的设置,如果是false,那么当前View不是事件的责任人,根据DispatchTouchEvent逻辑继续向下传递事件;如果为true,则当前View消费该事件,并不再向外传递。

3、实践
OrderedBroadcast(有序广播)的接收器,根据设置的不同权限,按顺序处理广播。

九、解释器模式



1、使用场景
用于解释含有终结符与非终结符的文法。
2、Android中的解释器模式
PackageParser解释AndroidManifest.xml文件
3、优缺点



十、命令模式


1、使用场景
(1)需要抽象出待执行的动作,然后以参数的形式提供出来——类似于过程设计中的回调机制,二命令模式正是毁掉机制的一个面向对象的替代品
(2)在不同的时刻指定、排列和执行请求。一个命令对象可以有与初始请求无关的生存期。
(3)支持取消操作,支持修改日志功能,支持事务操作。

2、安卓中的命令模式
PackageManagerService中对应用包的解析、管理、卸载等操作,使用命令模式,有内部类PackageHandler承担,其将需要处理的请求作为对象通过消息传递给相关的方法,而对于包的安卓、移动以及包大小的测量则分别封装为HandlerParams的3个具体子类InstallParams、MoveParams和MeasureParams。

3、实践
GUI中实现绘图板功能:绘制线条、支持撤销、重绘与历史记录功能。

十一、观察者模式


1、使用场景
(1)事件多级触发场景
(2)跨系统的消息交换场景,如消息队列、事件总线的处理机制。

2、安卓中的观察者模式
(1)ListView中的notifyDataSetChanged()方法。
(2)安卓的广播机制:接收对象通过Context的registerReceiver函数注册到AMS,当通过sendBroadcast发送广播时,所有注册了对象的IntentFilter的BroadcastReceiver对象就会接收到这个消息,BroadcastReceiver的onReceive方法就会被调用。

3、实践
EventBus的实现原理:
注解机制+反射+线程切换+观察者模式

4、优缺点


十二、备忘录模式



1、使用场景
(1)需要保存一个对象在某一个时刻的状态或部分状态
(2)如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以直接访问其内部状态。

2、安卓中的备忘录模式
Activity的状态保存机制:onSaveInstanceState与onRestoreInstanceState。

3、实践
记事本应用:支持文本与游标的保存、撤销、重做。

4、优缺点


十三、迭代者模式



1、使用场景
遍历一个容器对象

2、安卓中的迭代者模式
数据库查询时使用的Cursor。

十四、模板方法模式



1、使用场景
(1)多个子类有公有的方法,并且逻辑基本相同时。
(2)重要的、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
(3)重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。

2、安卓中的模板方法模式
Activity的生命周期函数(onCreate、onResume等)、AsyncTask的onPreExecute、doInBackground、onPostExecute。

3、优缺点


十五、访问者模式



1、使用场景
(1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
(2)需要对一个对象结构中的对象记性很多不同的悲切不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。

2、安卓中的访问者模式
JVM的注解处理机制——APT(Annotation Processing Tools)


附ButterKnife工作流程:
当你编译你的Android工程时,ButterKnife工程中 ButterKnifeProcessor 类的 process() 方法会执行以下操作:
(1)开始它会扫描Java代码中所有的ButterKnife注解 @Bind 、 @OnClick 、 @OnItemClicked 等。
(2)当它发现一个类中含有任何一个注解时, ButterKnifeProcessor 会帮你生成一个Java类,名字类似 <className>$$ViewBinder ,这个新生成的类实现了 ViewBinder<T> 接口。
(3)这个 ViewBinder 类中包含了所有对应的代码,比如 @Bind 注解对应 findViewById() , @OnClick 对应了 view.setOnClickListener() 等等。
(4)最后当Activity启动 ButterKnife.bind(this) 执行时,ButterKnife会去加载对应的 ViewBinder 类调用它们的 bind() 方法。

3、优缺点

十六、中介者模式


1、使用场景
当对象之间的交互操作很多且每个对象的行为操作都依赖彼此时,为防止在修改一个对象的行为时,同时设计修改很多其他对象的行为,可采用中介者模式,来解决紧耦合问题。该模式将对象之间的多对多关系变成一对多关系,中介者对象将系统从网状结构变成以中介者为中心的星型结构。

2、安卓中的中介者模式
Android的Binder机制,ServiceManager与Bingder 驱动实现了客户端与服务端通信的中介者。

3、实践
UI中的多个控件彼此相关,存在依赖关系的情形,可以使用中介者模式。


十七、代理模式



1、使用场景
当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
(1)远程代理:为某个对象在不同的内存地址空间提供绝不代理。使系统可以将Server部分的实现隐藏,以便Client可以不必考虑Server的存在。
(2)虚拟代理:使用一个代理对象表示一个十分耗资源的对象并在正在需要时才创建。
(3)保护代理:使用代理控制对原始对象的访问。该类型的代理常被用于原始对象有不同访问权限的情况。
(4)智能代理:在访问原始对象时执行一些自己的附件操作并对指向原始对象的引用计数。

2、安卓中的代理模式
ActivityManagerProxy与AMS之间的关系就是代理模式(远程代理,类似的还有WindowManagerProxy与WMS)。

3、动态代理
实现动态代理接口InvocationHandler,然后使用类似反射的方法调用Invoke方法。

4、实践
在原始功能类的基础上增加缓存、Log系统等,可以使用代理模式。

十八、组合模式


1、使用场景
(1)树形结构,表示对象的部分-整体层次结构时。
(2)从一个整体汇总能够独立出部分模块或功能的场景。
2、安卓中的组合模式
View系统中的View与ViewGroup之间的关系。

3、实践
操作系统中文件与文件夹的关系就可以使用组合模式。
4、优缺点


十九、适配器模式



1、使用场景
(1)系统需要使用现有的类,而此类的接口不符合系统的需要,即接口不兼容。
(2)想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
(3)需要一个统一的输出接口,而输出端的类型不可预知。

2、安卓中的适配器模式
LiastView的Adapter使用的就是适配器模式。

3、实践
自定义View时,使用适配器模式分离UI布局与数据之间的关系,让用户自定义UI与数据的联系。

二十、装饰模式


1、使用场景
需要透明且动态地扩展类的功能时。

2、安卓中的装饰模式
ContextImpl,Context,Activity,ContextThemeWrapper,ContextWrapper之间即是装饰模式。抽象方法:startActivity。上图中的Component对应Context,ConcreteComponent对应ContextImpl,Decorator对应ContextWrapper,ConcreteDecorator对应ContextThemeWrapper(Activity)。

3、实践
封装应用的入口检测功能,如检测包括版本检测、数据检测、设备检测等等,可以动态决定需要哪些检测。

二十一、享元模式




1、使用场景
(1)系统中存在大量的相似对象。
(2)细粒度的对象都具备较接近的外部状态,而且内部状态与环境五官,也就是说对象没有特定身份。
(3)需要对象缓冲池的场景。

2、安卓中的享元模式
安卓的Message系统,拥有一个Message的对象缓存池。由于对象缓存池的存在,安卓推荐使用Message.obtain()方法从缓存池中取空闲的消息,避免Message对象的频繁创建与销毁。

3、实践
Web开发中网络交互频繁的消息对象,适合使用享元模式。

4、优缺点


二十二、外观模式



1、使用场景
(1)为一个复杂子系统提供一个简单接口
(2)当你需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。

2、安卓中的外观模式
Context为Activity,Service,Broadcast封装了许多重要的高层接口。Context为外观抽象类,ContextImpl为外观类。

3、实践
对于SDK或者开源库,都要提供一个统一的高层接口,使用外观模式最为合适。

4、优缺点


二十三、桥接模式


1、使用场景
(1)如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,可以通过桥接模式使他们在抽象层建立一个关联关系。
(2)对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,也可以考虑使用桥接模式
(3)一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
(4)需要体现组合/聚合优先原则时,可以使用桥接模式。

2、安卓中的桥接模式
View的视图层级(Button、TextView等)与绘图类(HardwareLayer、Canvas等)的关系即为桥接模式。
Window与WindowManager之间也是桥接模式。

3、实践
绘制图形,图形有两种扩展——颜色、形状,可以使用桥接模式。

0 0