您的位置:首页 > 移动开发 > Android开发

android学习日记-5 观察者模式

2014-05-19 18:34 423 查看
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, 1000, 0, 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)缺点

可能会引起多余的数据通知。
可能会导致通知数据循环,导致死锁产生。

JAVA 观察者模式


观察者模式的组成

  抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

  抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。

  具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。

  具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。


程序实例

  通过程序实例来说明观察者模式:

  首先定义抽象的观察者:
//抽象观察者角色
public interface Watcher
{
public void update(String str);

}


然后定义抽象的主题角色,即抽象的被观察者,在其中声明方法(添加、移除观察者,通知观察者):

//抽象主题角色,watched:被观察
public interface Watched
{
public void addWatcher(Watcher watcher);

public void removeWatcher(Watcher watcher);

public void notifyWatchers(String str);

}


  然后定义具体的观察者:

public class ConcreteWatcher implements Watcher
{

@Override
public void update(String str)
{
System.out.println(str);
}

}


  之后是具体的主题角色: 

import java.util.ArrayList;
import java.util.List;

public class ConcreteWatched implements Watched
{
// 存放观察者
private List<Watcher> list = new ArrayList<Watcher>();

@Override
public void addWatcher(Watcher watcher)
{
list.add(watcher);
}

@Override
public void removeWatcher(Watcher watcher)
{
list.remove(watcher);
}

@Override
public void notifyWatchers(String str)
{
// 自动调用实际上是主题进行调用的
for (Watcher watcher : list)
{
watcher.update(str);
}
}

}


 编写测试类:

public class Test
{
public static void main(String[] args)
{
Watched girl = new ConcreteWatched();

Watcher watcher1 = new ConcreteWatcher();
Watcher watcher2 = new ConcreteWatcher();
Watcher watcher3 = new ConcreteWatcher();

girl.addWatcher(watcher1);
girl.addWatcher(watcher2);
girl.addWatcher(watcher3);

girl.notifyWatchers("开心");
}

}


参考文献:/article/4672763.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: