Android使用的设计模式1——观察者模式
设计模式,对程序员来说是一个坎,想在程序员这条路走得更远,设计模式是你的必修课。从大学时代接触GoF到工作几年后重新看设计模式,每次感觉都不一样。这次想借着分析Android Framework源码的机会,顺道整理一下设计模式的知识。
今天主要是先讲一下观察者模式,观察者模式对于做系统或者做公共库的朋友来说,应该很熟悉,基本上所有系统都会用到这个模式。整理的时候,主要是对模式进行进步讲解然后结合Android里面应用进行说明。设计模式的说明主要是参考《研磨设计模式》这本书,这本书讲解了GoF里面23种模式,而且比GoF更容易理解。如果对设计模式不了解的朋友,可以看看《研磨设计模式》这本书。
结合Android源码的时候,主要是针对应用层的代码说明,而且尽量使用简单例子代码,所以不会出现太多Android系统级的代码,大部分是我们做APP开发时会编写的代码。
这篇文章不会详细介绍设计模式,只是整理设计模式核心概念,结合Android应用说明。
(PS:新建的QQ群,有兴趣可以加入一起讨论:Android群:322599434)
1、观察者模式
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式最常用在我们熟悉的事件驱动模型里面,像VC、Android界面里面的事件响应,就是基于观察者模式来实现。
下面我们看看观察者模式的类图关系(图片是截取《研磨设计模式》里面插图):
- Subject是我们定义目标对象,或者说被观察对象。
- ConcreteSubject是实际的被观察对象。
- Observer是观察者的接口,定义了回调接口。
- ConcreteObserver是实际的观察者对象。
2、观察者模式含义
下面讲解一下个人对观察者模式的理解,其实这个模式在我们平时工作中是很常用的模式,可能你已经使用过,缺没有意识到。
观察者模式主要是针对一对多的数据更新。简单来说就是,系统里面某个元素更新了数据,然后有好几个元素是使用了这个元素的数据。此时更新了数据的对象,就要通知其他使用了它数据的对象,让他们都进行更新。
标准的观察者对象是一对多的关系,不过我们都知道设计模式里面是很灵活,在我们使用的时候,经常需要进行变形。对现有的标准模式进行适当的修改来适应设计需求。
在我们实际应用中,还会遇到一对一、或者多对一的情况。一对一就是,一个目标对应一个观察者。多对一是指多个目标对应一个观察者。
3、观察者模式的简单实现
下面给出一个最简单的观察者模式实现代码,把代码看懂了,再回头看文字讲解,会比较容易理解。下面是目标对象的接口和实现代码,只做了一个最简单的接口。
//Edited by mythou
//http://www.cnblogs.com/mythou/
//目标对象接口
public interface Subject
{
//调用这个方法注册一个新的观察者对象
public void attach(Observer observer); //调用这个方法删除一个已注册的观察者对象
public void detach(Observer observer); //调用这个方法通知所有注册的观察者对象
void notifyObservers();
} //目标对象实现
public class ConcreteSubject implements Subject
{
//向量容器,保存所有注册的观察者
private Vector observersVector = new Vector(); public void attach(Observer observer)
{
observersVector.addElement(observer);
} public void detach(Observer observer)
{
observersVector.removeElement(observer);
} public void notifyObservers()
{
Enumeration enumeration = observers(); while(enumeration.hasMoreElements())
{
((Observer)enumeration.nextElement()).update();
}
}
}
下面是观察者的实现:
//Edited by mythou
//http://www.cnblogs.com/mythou/
//观察者接口
public interface Observer
{
void update();
} //观察者实现
public class ConcreteObserver implements Observer
{
public void update()
{
System.out.println("The subject has changed! mythou notify");
}
}
应用中使用的代码:
//Edited by mythou
//http://www.cnblogs.com/mythou/
//客户端
public class Client
{
private static ConcreteSubject subject;
private static Observer observer; public static void main(String args[])
{
//创建目标对象
subject = new ConcreteSubject();
//创建观察者对象
observer = new ConcreteObserver();
subject.attach(observer);
subject.change("mythou has changed data!");
}
}
4、Android 应用开发中的观察者模式
在我们做Android应用的时候,会大量使用观察者模式,因为Framework层里面的事件驱动都是基于观察者模式实现的。另外在Framework层里面的各种服务在数据变更的时候,也是通过观察者模式实现上层数据更新。下面会讲两个例子来说明:
A)控件中Listener监听方式
Android里面最典型的观察者就是我们使用的各种控件监听者。例如下面对某个按钮的监听:
//Edited by mythou
//http://www.cnblogs.com/mythou/
Button baiduclickButton = (Button)findViewById(R.id.button1);
//注册观察者
baiduclickButton.setOnClickListener(new OnClickListener()
{
//观察者实现
@Override
public void onClick(View arg0)
{
Log.d("Mythou_Log", "Click the button ");
}
});
例如上面的代码,注册了一个按钮的监听方法。这里实际上是应用了一对一的观察者模式,setOnClickListener()方法就是注册一个观察者,Button对象就是我们要观察的目标对象。而new出来的OnClickListener(),就是我们实际的观察者。
每当我们的目标按钮对象被点击,状态发生变化的时候,就会通过回调注册的OnClickListener观察者的onClick方法会来通知观察者,Button状态发生变化。这里的onClick相当于前面例子里面的update方法。下面是Android源码里面对OnClickListener的定义,跟我们前面定义一个观察者接口类似。
//Edited by mythou
//http://www.cnblogs.com/mythou/
public interface OnClickListener
{
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
B)GPS位置信息监听
上面对按钮监听是属于一对一的观察者模式,当然你也可以用一个Listener监听多个按钮。下面我们再讲一个标准的一对多的观察者模式的应用。在我们使用GPS模块的时候,需要监听GPS模块位置变化,通常我们会编写下面代码:
//Edited by mythou
//http://www.cnblogs.com/mythou/
// 通过GPS定位
String LocateType= locationManager.GPS_PROVIDER;
Location location = locationManager.getLastKnownLocation(LocateType);
// 设置监听器,设置自动更新间隔这里设置1000ms,移动距离:0米。
locationManager.requestLocationUpdates(provider, , , locationListener);
// 设置状态监听回调函数。statusListener是监听的回调函数。
locationManager.addGpsStatusListener(statusListener); //监听器实现
private final GpsStatus.Listener statusListener = new GpsStatus.Listener()
{
public void onGpsStatusChanged(int event)
{
// GPS状态变化时的回调,获取当前状态
GpsStatus status = locationManager.getGpsStatus(null);
//自己编写的方法,获取卫星状态相关数据
GetGPSStatus(event, status);
}
};
GPS位置服务是Framework的一个系统层服务,整个系统只有一个运行的实例。但实际使用时,可能会出现好几个应用都在使用这个服务,因此会形成了一个一对多的观察者例子。这里不对代码进行深入对比讲解,只要对照上面的讲解,你就可以把目标对象、观察者接口、观察者实现、数据更新回调接口找出来。有兴趣的朋友还可以追查Android的源码,看看GpsStatus里面的具体实现。
5、结语
除了上面说的按钮响应、GPS服务外,还有一个例子比较经典,就是我们的BroadcastReceiver响应,也是基于观察者模式来实现,下面总结里面也会说到,观察者模式支持广播通信。有关BroadcastReceiver是怎么实现观察者模式的,有兴趣的朋友可以自己对比代码,和查看Android实现源码,自己动手才能加深印象。引入设计模式是为了对系统有更深入的理解。下面总结一下观察者模式的优缺点,方便我们在使用的时候,可以根据实际情况衡量。
A)优点
- 实现观察者和目标对象之间的抽象耦合。
- 观察者模式支持广播通信。被观察者会所有的登记过的观察者发出通知。
B)缺点
- 可能会引起多余的数据通知。
- 可能会导致通知数据循环,导致死锁产生。
Edited by mythou
原创博文,转载请标明出处:http://www.cnblogs.com/mythou/p/3370340.html
Android使用的设计模式1——观察者模式的更多相关文章
- Android中的设计模式之观察者模式
参考 <设计模式:可复用面向对象软件的基础 >5.7 Observer 观察者 对象行为型模式 <设计模式解析> 18.4 Observer模式 <Android源码设计 ...
- Android 经常使用设计模式(一)
由于项目变更的频繁性,作为一名程序猿,我们须要掌握设计模式的必要性.就不言而喻~~.以下就是一些我自己学习的设计模式总结. 接下来,主要是针对几个比較经常使用模式进行解说,主要是以下几种: 观察者模式 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式之观察者模式(Observable与Observer)
设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...
- 《Android源码设计模式》学习笔记之ImageLoader
微信公众号:CodingAndroid cnblog:http://www.cnblogs.com/angel88/ CSDN:http://blog.csdn.net/xinpengfei521 需 ...
- 8.5 GOF设计模式四: 观察者模式Observer
GOF设计模式四: 观察者模式Observer 现实中遇到的问题 当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式 观察者模式 ...
- [转] Android中的设计模式-备忘录模式
转自Android中的设计模式-备忘录模式 定义 备忘录设计模式的定义就是把对象的状态记录和管理委托给外界处理,用以维持自己的封闭性. 比较官方的定义 备忘录模式(Memento Pattern)又叫 ...
- Android经常使用设计模式(二)
继上一篇 Android经常使用设计模式(一)里认识了观察者.适配器.代理等三种模式,这一篇将会解说下面三种模式: 工厂模式 单例模式 命令模式 1.工厂模式(Factory Pattern) 工厂模 ...
- php 设计模式之观察者模式(订阅者模式)
php 设计模式之观察者模式 实例 没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则 介绍 观察者模式定义对象的一对多依赖,这样一来,当一个对象改 ...
随机推荐
- VS2010中使用GDAL(一)
初次使用visual studio 对工具不熟悉,有些步骤可以配置的 (1)在VS2005中新建win32控制台程序 testGDALconsole,(向导中附加选项不能选为空项目) 将C:\GDAL ...
- objective-c 创建工程/编译/运行程序
// First program example #import <Foundation/Foundation.h> int main (int argc, const char * ar ...
- Robot Framework-DatabaseLibrary数据库(MySql)
Robot Framework-Mac版本安装 Robot Framework-Windows版本安装 Robot Framework-工具简介及入门使用 Robot Framework-Databa ...
- mfc 在VC的两个对话框类中传递参数的三种方法
弄了好久,今天终于把在VC中的对话框类之间传递参数的问题解决了,很开心,记录如下: 1. 我所建立的工程是一个基于MFC对话框的应用程序,一共有三个对话框,第一个对话框为主对话框,所对应的类为CTMD ...
- write函数出错返回invalid argument(EINVAL)问题
还是在下载机上面遇到的. 话说为了长久的下载,后面又买了个16G的U盘格成EXT3放在角落下载,结果发现总是有几个种子在下载的时候会出错提示invalid argument. 之前也出过一样的错误提示 ...
- URAL 1915 Titan Ruins: Reconstruction of Bygones(思路)
搞这个题差不多是从比赛开始到结束. 从自信慢慢的看题一直到wrong到死. 这个题目可以说成是思路题,以为我们只要明白一点,这道题就成了纯暴力的水题, 那就是当操作数不足栈中数字数目的时候,我们就没有 ...
- iPad上的Cookie到底有多长?
[故事背景]: 公司某个站点,特别依赖Cookie的使用,而且用的比较狠.在设计之初想当然地以为到达Cookie上限是猴年马月的事儿,没想到时过境迁,这个上限真的来了. 着手改吧,也不想投入太多.于是 ...
- 从0开始学Swift笔记整理(四)
这是跟在上一篇博文后续内容: --重写方法 重写实例方法 在子类中重写从父类继承来的实例方法和静态方法.先介绍实例方法的重写. 下面看一个示例: class Person { var n ...
- Win2012R2的一个Bug---安装群集后可能引发的软件崩溃问题及相应补丁
如标题,笔者查阅资料发现微软声称安装故障转角色后就可能发生上述描述问题,但不止于SSMS崩溃.建议使用win2012R2的朋友安装补丁. 笔者在部署win2012R2+Sql2014 cluster时 ...
- Magicodes.WeiChat——WeChatOAuthTest(网页授权获取用户基本信息)
Demo访问地址:http://wechat.magicodes.net/app/AppDemo/WeChatOAuthTest?tenantId=1 关于公众号如何获取用户信息,请参考此文档:htt ...