Android常用8种设计模式(二)
今天接着昨天的内容聊,主要有观察者模式、代理模式、命令模式。--文章整理自博客园
观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下。
本文以AbstractCursor为例子,展开分析。
观察者模式,Observer Pattern,是一个很实用的模式,本人曾经接触到的各种平台以及曾经参与项目中打印模板解释器中都用到了此模式。
1.意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
热门词汇:依赖 发布-订阅 事件 通知 更新 监听
2.结构
这是一个最简单的观察者模式,目标对象能够添加和删除观察者,当自己某种状态或者行为发生改变时,可通过notify通知注册的观察者进行更新操作。
分析AbstractCursor的具体情况,我们发现实际工作有时需要对观察者进行统一管理,甚至观察者类型有很多种而又可以分成几个系列,这个时候是要复杂的多,通过合理的分层这个问题很好解决。下面根据具体情况,我们画出android中abstractCurosr中用到的观察者模式结构图:
观察者分成了两个系列。
3.代码 列举其中相关核心代码如下:
public abstract class AbstractCursor {
//定义管理器
DataSetObservable mDataSetObservable = new DataSetObservable();
ContentObservable mContentObservable = new ContentObservable();
//注册和卸载两类观察者
public void registerContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
public void unregisterContentObserver(ContentObserver observer) {
// cursor will unregister all observers when it close
if (!mClosed) {
mContentObservable.unregisterObserver(observer);
}
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
//2类通知方法
protected void onChange(boolean selfChange) {
synchronized (mSelfObserverLock) {
mContentObservable.dispatchChange(selfChange);
if (mNotifyUri != null && selfChange) {
mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
}
}
}
protected void notifyDataSetChange() {
mDataSetObservable.notifyChanged();
}
}
再看看Observable类和DataSetObservable类:
public abstract class Observable<T> {
/**
* 观察者列表
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
和
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* 数据发生变化时,通知所有的观察者
*/
public void notifyChanged() {
synchronized(mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onChanged();
}
}
}
//... ... (其他方法)
}
观察者DataSetObserver类是一个抽象类:
public abstract class DataSetObserver {
public void onChanged() {
// Do nothing
}
}
所以我们具体看它的子类:
public class AlphabetIndexer extends DataSetObserver{
/*
* @hide 被android系统隐藏起来了
*/
@Override
public void onChanged() {
//观察到数据变化,观察者做自己该做的事情
super.onChanged();
mAlphaMap.clear();
}
}
ContentObserver也是类似。
4.效果
(1).行为型模式
(2).目标和观察者间的抽象耦合(经典实现)。
(3).支持广播通信(相信这点android开发者看到后应该有启发吧)。
(4).注意意外的更新,这也是观察者更新进行管理的原因之一。
代理模式请参看:
http://blog.csdn.net/qq_27489007/article/details/53426428
命令模式,在.net,java平台的事件机制用的非常多,几乎每天都与之打交道。
android中对我印象最深的就是多线程多进程的环境,所以必然大量使用到Runbable,Thread,其实用的就是最简单的命令模式。
命令模式,Command Pattern,把请求封装为一个对象,多么巧妙的一个说法啊。
1.意图
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
热门词汇:动作 事物 请求封装 排队 打包 异步
2.结构
Command接口提供了Execute方法,客户端通过Invoker调用命令操作来调用Recriver,绕了一大圈,
但是却把具体对Receiver的操作请求封装在具体的命令中,是客户端对recriver的操作清晰简明。
但是在实际项目中,我们常常忽略Receiver,而把命令对象的目标对象直接设置为子类自己的成员变
量或者作为execute()方法的临时变量。
以Android中的Runnable(在java.lang包下)为例,我们画出UML结构图如下:
想不到我们天天写的代码无意识中就是用到了命令模式,所谓模式,就是无所不在。
3.代码
命令接口Runnable定义如下:
public interface Runnable {
public abstract void run();
}
调用者Thread简化版代码:
//命令模式这里不需要继承Runnable接口,但是这里考虑到实际情况,比如方便性等,继承了Runnable接口,实现了run方法,这个是Thread自身的运行run的方法
class Thread implements Runnable {
private Runnable target;
public Thread(Runnable target) {
this.target = target;
}
public synchronized void start() {
if (threadStatus != 0 || this != me)
throw new IllegalThreadStateException();
group.add(this);
start0();//这个是本地方法,调用run方法
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
//可选
public void run() {
if (target != null) {
target.run();
}
}
}
客户端只需要new Thread(new Runnable(){}).start()就开始执行相关的一系列的请求,这些请求大部分都是实现Runnable接口的匿名类。
4.效果
(1).行为型模式;
(2).将调用对象的操作和知道如何实现该操作的对象解耦;
(3).多个命令可以装配成一个复合命令;
(4).增加新的命令很容易。
📢作者:小空和小芝中的小空
📢转载说明:务必注明来源:https://zhima.blog.csdn.net/。
📢欢迎点赞👍收藏🌟留言📝
📢链接Q群:👪技术:204918251 👪资源:877807592
相关文章
- android studio不能输入中文_Android模拟器
- 2019最新Android面试题「建议收藏」
- Android常用加密库集合
- 74款android开机动画,修改Android系统开机动画
- android 常用加密,分享一下Android各种类型的加密
- 代码加密 android,Android 开发怎样做代码加密或混淆「建议收藏」
- android activity singletask,Android Activity启动模式之singleTask实例详解
- android 模拟器 haxm,Android模拟器不使用HAXM
- android sdk根目录,Android SDK位置
- Android startActivityForResult用法
- android-短信验证功能,Android实现获取短信验证码的功能以及自定义GUI短信验证详解…
- android telephony 原理解析与开发指南_Android逆向pdf
- android系统中toast是什么_Android个人资料简单布局
- android studio usb连接手机_android studio怎么用真机调试
- Android n_android 反编译
- android的layout_android可拖拽layout
- android跳转到相册需要权限,Android打开相册获取图片路径[通俗易懂]
- android进程间通信方式有哪几种_安卓进程间通信
- Android Services Library_android freeware
- android sqlite 判断表和表中字段是否存在方法
- 【Android NDK 开发】JNI 方法解析 ( 字符串数组参数传递 | 字符串遍历 | 类型强转 | Java 字符串与 C 字符串转换 | 字符串释放 )
- 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交叉编译 | Android 静态库交叉编译 )
- 【Android 内存优化】Bitmap 内存占用计算 ( Bitmap 图片内存占用分析 | Bitmap 内存占用计算 | Bitmap 不同像素密度间的转换 )
- 【错误记录】Flutter / Android 报错 ( AAPT: error: attribute android:requestLegacyExternalStorage not found )
- 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 三 )
- 【Android 逆向】Android 逆向基本概念 ( 软件运行时内存结构 | 文件与内存之间的联系 )
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( ./init-android.sh: 第 37 行: cd: android/contrib/: 没有那个文件或目录 )
- 【Android Gradle 插件】主工程依赖指定 Library 的特定变体 ( LibraryExtension#publishNonDefault 配置 | 依赖指定 Library 变体 )
- Android开发中遇到的问题(二)——新建android工程的时候eclipse没有生成MainActivity和layout布局详解手机开发
- 深入理解Android插件化技术详解手机开发
- Android中android:visibility的3中属性的剖析详解手机开发
- 安卓编年史(14):Android 2.3 Gingerbread——第一次 UI 大变
- Android实现PHP连接MySQL进行数据交互(android通过php连接mysql)
- 如何看待 Kotlin 成为 Android 官方支持的开发语言?一线开发者这样说
- Android中的android:layout_weight使用详解
- Android调用系统的发邮件功能的小例子
- Android下通过httpClient发送GET和POST请求的实例代码