观察者模式又称为发布—订阅Subscriblem模式。
观察者模式(Obsrever)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象涉及的一个原则是:单一职责原则。系统中的每个类将重点放在一个功能上,而不是其他方面。一个对象只做一件事,并且将它做好。观察者模式在模块之前划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发送变化时,所有依赖于它的对象都得到通知并并自动刷新。
观察者实现模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察者对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在"观察"的逻辑关联,当被观察者发生改变的时候,可以确保界面和数据之间划清界限,假定应用程序的需求发送变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。
实现观察者模式的时候要注意,观察者和被观察者之间的关系不能体现为类之间的直接调用,否则就将使观察者和被观察者对象之间紧密的耦合起来,从根本上违反面向对象的设计原则。无论是观察者"观察"观察对象,还是被观察者将自己的改变"通知"观察者,都不应该直接调用。
观察者模式分为Push(被观察者将自己的改变"通知"观察者)和Pull(观察者"观察"观察对象)两种实现方式。一般常见的是使Push模式。
实现观察者模式有很多形式,比较直观的一种是使用"注册—通知—撤销注册"的形式。下面的三个图详细的描述了这样一种过程:
观察者
(Observer)将自己注册到被观察者对象(Subject)中,被观察者对象将观察者存放在一个容器(Container)里。
被观察者
被观察者对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。
撤销观察
观察者告诉被观察者要撤销观察、被观察者从容器里将观察者去除。
观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,它可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。
具体例子
下面以项目中遇到的一个非常适合观察者模式的实际应用场景为例来讲解:实际项目中,我们可能 会经常遇到下载的情况。当有多个下载任务在后台下载时,下载任务是被观察者,下载任务列表页面是 观察者对象。
这里使用观察者模式的好处是:
1.让业务逻辑和界面显示分离,实现MVC分层
2.节省资源,让页面不可见时,注销观察者,这样就不再刷新View。
public interface DownloadObserver { void onDownloadChanged(); }
//观察者对象1 public class DldingJobActivity implements DownloadObserver{ ...... @Override protected void onPause() { ...... //注销观察者 Dld.getInstance().deregisterDownloadObserver(this); super.onPause(); } @Override protected void onResume() { ...... //注册观察者 Dld.getInstance().notifyObservers(); super.onResume(); } @Override public void onDownloadChanged() { //得到通知,更新UI mHandler.post(mUpdateTimeTask); } ...... }
//观察者对象2 public class DownloadJobActivity implements DownloadObserver{ ...... @Override protected void onPause() { ...... //注销观察者 Dld.getInstance().deregisterDownloadObserver(this); super.onPause(); } @Override protected void onResume() { ...... //注册观察者 Dld.getInstance().notifyObservers(); super.onResume(); } @Override public void onDownloadChanged(){ //得到通知,更新UI ....... } ...... }
//被观察者对象 public class DownloadJob{ ...... public void setDownloadedSize(long downloadedSize) { if (downloadedSize == mDownloadedSize) { return; } mDownloadedSize = downloadedSize; int tempProgress = 0; tempProgress = (int) ((mDownloadedSize * 100) / mTotalSize); if (tempProgress != mProgress) { mProgress = tempProgress; Dld.getInstance().notifyObservers(); } } ....... }
public class Dld{ private static Dld instance; private ArrayList<DownloadObserver> mObservers; public static Dld getInstance() { if (instance == null) { instance = new Dld(); } return instance; } public Dld(){ mObservers = new ArrayList<DownloadObserver>(); } public synchronized void deregisterDownloadObserver(DownloadObserver observer) { mObservers.remove(observer); } public synchronized void registerDownloadObserver(DownloadObserver observer) { mObservers.add(observer); } public synchronized void notifyObservers() { for (DownloadObserver observer : mObservers) { observer.onDownloadChanged(this); } } }
Java里提供了相关的API方便我们实现Observer模式。相关实现如下:
public class MainActivity{ ...... private void initNetErrorObserver() { try { mNetErrorView = findViewById(R.id.net_error_layout); NetMonitor.getInstance().addObserver(mNetObserver); } catch (Exception e) { } } private NetObserver mNetObserver = new NetObserver() { @Override public void notify(NetAction action) { if (mNetErrorView == null) return; if (action.isAvailable()) { mNetErrorView.setVisibility(View.GONE); } else { mNetErrorView.setVisibility(View.VISIBLE); } } }; ...... }
public class NetMonitor extends BroadcastReceiver{ private final static String TAG = "NetMonitor"; //observable object for the net monitor private NetObservable observable = null; //single instance of network monitor private static NetMonitor instance = null; public static NetMonitor getInstance(){ if(instance == null){ instance = new NetMonitor(); } return instance; } public void init(Context context){ this.observable = new NetObservable(context); //filter the network connectivity change action //broadcast message IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); //register the broadcast receiver context.registerReceiver(this, filter); } public void addObserver(FSNetObserver observer){ this.observable.addObserver(observer); } public void delObserver(FSNetObserver observer){ this.observable.deleteObserver(observer); } @Override public void onReceive(Context context, Intent intent) { this.notifyNetState(context); } private void notifyNetState(Context context){ try{ //network state changed, get current network state NetworkInfo ni = FSDevice.Network.getCurrentActiveNetwork(context); if(ni != null){ if(!ni.isAvailable()){ this.observable.notifyObservers(new FSNetObserver.NetAction(false, false, false)); }else{ if(ni.getType() == ConnectivityManager.TYPE_WIFI){ this.observable.notifyObservers(new FSNetObserver.NetAction(true, true, true)); }else{ this.observable.notifyObservers(new FSNetObserver.NetAction(true, false, false)); } } }else{ this.observable.notifyObservers(new FSNetObserver.NetAction(false, false, false)); } }catch(Exception e){ FSLogcat.e(TAG, e.getMessage()); } } public void destory(){ this.observable.deleteObservers(); } }
public class NetObservable extends Observable{ private final String TAG = "NetObservable"; //must be application's context private Context context = null; public NetObservable(Context context){ super(); this.context = context; } @Override public void addObserver(Observer observer) { try{ super.addObserver(observer); NetworkInfo ni = Device.Network.getCurrentActiveNetwork(context); if(ni != null){ if(!ni.isAvailable()){ observer.update(this, new NetObserver.NetAction(false, false, false)); }else{ if(ni.getType() == ConnectivityManager.TYPE_WIFI){ observer.update(this, new NetObserver.NetAction(true, true, true)); }else{ observer.update(this, new NetObserver.NetAction(true, false, false)); } } }else{ observer.update(this, new NetObserver.NetAction(false, false, false)); } }catch(Exception e){ Logcat.e(TAG, e.getMessage()); } } @Override public void notifyObservers(Object data){ try{ this.setChanged(); super.notifyObservers(data); }catch(Exception e){ Logcat.e(TAG, e.getMessage()); } } }
相关推荐
在给定的标题“设计模式 之 观察者模式”中,我们可以理解到这个压缩包文件主要关注的是观察者模式在实际应用中的示例。观察者模式的核心概念包括观察者(Observer)和主题(Subject),其中观察者是接收通知的对象...
观察者模式(Observer Pattern)是一种软件设计模式,属于行为型模式之一。它定义了对象间的一种一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。这种模式可以有效地实现...
**观察者模式(Observer Pattern)**是软件设计模式中的一种行为模式,它在Java中有着广泛的应用。这个模式的核心思想是“一对多”的依赖关系,即一个主题对象(Subject)可以被多个观察者(Observer)关注,当主题...
观察者模式(Observer Pattern)是设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式在软件开发中广泛应用于事件驱动...
### 设计模式之观察者模式详解 #### 一、观察者模式概述 观察者模式(Observer Pattern)是一种常用的行为设计模式,它允许对象之间建立一种一对多的关系,即多个对象可以监听一个对象的状态变化,当这个对象的...
期末复习资料“软件设计模式之观察者模式(复习5)代码”很可能包含了关于观察者模式的详细讲解,以及相关的代码示例,帮助学生巩固理解。 观察者模式主要由两个关键角色构成:主题(Subject)和观察者(Observer)...
观察者模式(Observer Pattern)是软件设计模式中的行为模式之一,它在Android开发中有着广泛的应用。该模式的主要目的是定义对象之间的一种一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会...
**Java设计模式之观察者模式详解** 在软件工程中,设计模式是一种被广泛接受的解决常见问题的方法。观察者模式(Observer Pattern)是行为设计模式的一种,它定义了对象之间的一对多依赖关系,当一个对象的状态发生...
观察者模式(Observer Pattern)是软件设计模式中的一种行为模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式常用于事件驱动的系统或者...
观察者模式(Observer)是软件设计模式中的一种行为模式,其主要目的是在对象之间建立一种松散耦合的关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件驱动...
本篇文章将深入探讨Qt中的观察者模式(Observer Pattern),这是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。 观察者模式的核心...
观察者模式,也被称为发布-订阅模式或事件驱动模式,是软件设计模式中的一种行为模式。这个模式的主要目的是在对象之间建立一种松散耦合的关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并...