问题: 请阐述至少5中安卓中常用的设计模式
定义: 什么是设计模式? 为解决一个问题或实现一个功能的一种固定的代码模式。
- callback 回调 [各种on....方法]
- template 模板 [各种Base...抽象类]
- flyweight 享元模式 [message池,即obtainMessage]
- observer观察者 [BaseAdapter.notifyDataChanged....]
- adapter适配器
- singleton单例
- proxy代理
- builder创建者
以Button.onClick()
为例,在onClick
方法处打断点分析源码
打开AS调试窗口查看onClick
调用顺序,发现onClick
由performClick
直接调用的。 那么问题就来了,为什么不直接在Activity
中调用performClick
呢?
原因:
- 事件在
Button
里面,点击事件什么时候发生?不知道,由用户决定,所以必须由Button
来调用- 多态,如果不这样那么,就需要定义各种不同的
onCLick
方法,如Activity.onClick
,Fragment.onClick
, 那不如暴露一个统一的接口,当点击事件发生时,直接listener.onClick
即可
- 定义: 定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
说人话:通用步骤在父类中实现,具体的操作在子类中实现。以刷牙为例
flyweight享元模式
定义: 复用我们内存中已存在的对象,降低系统创建对象实例的性能消耗
我们在这就以
Message
为例
既然这种模式(flyweight)是一种设计模式,那么肯定在其他地方有使用,百度或者google搜索可以找到。 这里世界在AS中搜索
sync + pool
, 找到android.support.v4.util.Pools
感受下:
observer观察者模式
以拍卖会为例:
使用观察者模式是有代码规范的:
Observable
的职责: 1,管理观察者; 2,当状态更新时,通知所有观察者
Observer
的职责: 1,管理观察者; 2,当状态更新时,通知所有观察者
这很容易让人想到,使用ListView时,数据或状态改变的时候会调用notifyDataSetChanged
,如下图所示:在ListView中动态地addHeaderView
查看源码流程: BaseAdapter.notifyDataSetChanged
--- DataSetObservable.notifyChanged
适配器设计模式
接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题。程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库的发展和进化。
例子1:iphone4,你即可以使用UBS接口连接电脑来充电,假如只有iphone没有电脑,怎么办呢?苹果提供了iphone电源适配器。可以使用这个电源适配器充电。这个iphone的电源适配器就是类似我们说的适配器模式。(电源适配器就是把电源变成需要的电压,也就是适配器的作用是使得一个东西适合另外一个东西。)
例子2:最典型的例子就是很多功能手机,每一种机型都自带有从电器,有一天自带充电器坏了,而且市场没有这类型充电器可买了。怎么办?万能充电器就可以解决。这个万能充电器就是适配器。
适配器模式(Adapter Pattern),把一个类的接口变换成客户端所期待的另一种接口, Adapter模式使原本因接口不匹配(或者不兼容)而无法在一起工作的两个类能够在一起工作。又称为转换器模式、变压器模式、包装(Wrapper)器模式(把已有的一些类包装起来,使之能有满足需要的接口)。
单例设计模式
一、单例模式要点
1.单例,顾名思义,某个类只能有一个实例。
2.它必须自行创建这个唯一的实例。
3.它必须自行向整个系统提供这个实例。
以下我就初略的介绍两种常用的单例类:
Proxy代理模式
1.初识代理模式
生活中大家一定遇到这样的情况了:比如说我要买一条毛巾,不妨就是洁丽雅的吧,那一般人的话我应该不是去洁丽雅的工厂里面直接去买吧,而是我们在洁丽雅专卖店或者什么超市啊,这些地方购买,这些地方实际上就是洁丽雅毛巾的代理。这其实和我们OO中的代理模式是很相似的。
一个it人士,上网应该是经常的事了吧,那么总会有这样的情况,打开一个网页,文字先出现,而那些比较大的资源,例如图片要等等才会显示出来,这是为什么呢??实际上这其中采用的就是代理模式。
2.代理模式的一个简单的例子
就说上面的毛巾的例子吧,将有如下类图:
3.代理模式的意义
代理模式到底好处在哪里呢??
那先要说一下代理模式中的三种角色了。
抽象角色:声明真实对象和代理对象的共同接口。
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
4.什么时候使用代理模式
当我们需要使用的对象很复杂或者需要很长时间去构造,这时就可以使用代理模式(Proxy)。例如:如果构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。一个代理(Proxy)通常包含和将要使用的对象同样的方法,一旦开始使用这个对象,这些方法将通过代理(Proxy)传递给实际的对象。 一些可以使用代理模式(Proxy)的情况:
一个对象,比如一幅很大的图像,需要载入的时间很长。
一个需要很长时间才可以完成的计算结果,并且需要在它计算过程中显示中间结果
一个存在于远程计算机上的对象,需要通过网络载入这个远程对象则需要很长时间,特别是在网络传输高峰期。
一个对象只有有限的访问权限,代理模式(Proxy)可以验证用户的权限
代理模式(Proxy)也可以被用来区别一个对象实例的请求和实际的访问,例如:在程序初始化过程中可能建立多个对象,但并不都是马上使用,代理模式(Proxy)可以载入需要的真正的对象。这是一个需要载入和显示一幅很大的图像的程序,当程序启动时,就必须确定要显示的图像,但是实际的图像只能在完全载入后才可以显示!这时我们就可以使用代理模式(Proxy)。
builder创建者
一个对象的创建十分复杂,为了区分构建过程和使用过程,因此分开。使用一个Director类进行对象的创建,Builder规定了这个创建过程。
模式结构为如图所示:
Builder 抽象建造者接口,规范各个组成部分的构建。
ConcreteBuilder 具体建造者角色,实现组成部分的构建,并提供示例。
Product 产品角色,创建返回的对象。
Director 导演者角色,负责创建以及使用。
1 当创建对象复杂并且与其使用过程独立。
2 构造过程允许构造的对象有不同的表示。