设计模式实战应用之二:观察者模式

原创 2013年12月04日 18:42:45
        观察者模式的定义
        观察者模式是应用最普遍的设计模式之一。著名的 MVC 模式就是观察者模式的应用之一;高性能网络应用框架 MINA 中的事件处理器也是观察者模式的应用之一,一旦有 I/O 事件,所有注册的 IoHandler 对象会被通知到,我们可以通过对这个接口的自定义扩展以实现相应业务处理;流媒体服务 Wowza Streaming Engine 的插件模块扩展开发也正是利用到了观察者模式,用户通过自定义模块对比如 com.wowza.wms.stream.IMediaStreamActionNotify 等接口的实现,可以捕捉到自己所关心的流的一系列事件,进而就可以对特定直播/点播频道进行监控了。Gof 把观察者模式归类到对象行为型模式,《设计模式:可复用面向对象软件的基础》对观察者模式做出了明确的定义:“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” 翻译过来就是:“定义了一些对象之间的一对多依赖关系,这样子当一个对象的状态发生变化时,所有依赖于这个对象的对象都会得到通知,并被自动更新”。
        why 观察者模式?
        把系统设计成一些互相合作的类有一个常见的弊端:需要维护相关对象之间的一致性。为了维护一致性而使各类紧密耦合,大大降低了模块的可复用性,这是我们不愿意看到的。
        观察者模式的使用场合
  • 当一个抽象模型具有一方依赖于另一方的两方面时,将它们封装在独立的对象中可以让你对它们独立地改变和复用。
  • 当对于一个对象的改变需要同时改变其他对象,而且你不知道有多少对象需要改变。
  • 当一个对象需要通知其他对象,又不能假定其他对象是谁,换句话说,你不希望这些对象紧密地耦合在一起。
        《多线程高效读取缓冲区数据》需求
        本文示例摒弃了那些枯燥无味、与我们项目毫无关联的鸭子啊报社啊葡萄园之类的,同时也因为抄来抄去而被用烂了的无聊话题,采用的是 CSDN 网友项目实战中真实遇到而提出来的一个问题作为案例进行分析。让我们切实感受设计模式带来的好处,领略设计模式的真正的威力,而不只是用来玩理论、侃大山。
        这个是网友 xgPaul 发帖提出的一个讨论。标题是《如何实现多线程高效的读取一块缓冲区中的数据???》帖子链接是:http://bbs.csdn.net/topics/390658695
        帖子正文描述如下:
        一条线程不断的对一块内存缓冲区进行写数据,同时几十条线程(几百个对象)要从该缓冲区中读取数据。这一过程如何实现高效与数据同步。(使用锁同步效率太低)
        《多线程高效读取缓冲区数据》分析
        xgPaul 遇到的这个问题,比较类似于上海抢拍车牌号的场景:一条线程不断地对当前价格进行刷新,同时几十条线程(几百个对象)对当前价格进行读取监控。用观察者模式效率比较好,可以解决由于线程竞争、加锁而带来的效率问题。把读数据的线程归为观察者,主题是缓冲区数据。一旦数据有更新,主题向观察者推送更新数据,这样推数据的做法效率很高。缓冲区做成主题,每个观察者都有一份自己关心的主题数据的本地备份,如果主题没有推数据过来,本地备份就是最新数据。当然,这么干稍耗空间,但是却换得多线程环境中效率上的大幅度提升,这就是所谓的用空间换时间。
        java.lang.ThreadLocal 就是这种原理的一个实现。
        《多线程高效读取缓冲区数据》类设计
        本文重在讲解模式,所以仅以一个 int 类型的数据 onlinePlayersNum 模拟缓冲区数据。两个发布板,一个公开发布板一个内部发布板作为观察者。
        由 BufferData 对象向两个发布板推数据,后者不需要去前者查询数据,只需要查询自己的状态是否改变以决定是否更新发布。具体类图设计如下:
观察者模式类图
        《多线程高效读取缓冲区数据》时序图
观察者模式时序图
        《多线程高效读取缓冲区数据》源码实现
        《设计模式:可复用面向对象软件的基础》的观察者模式中的 Subject 角色,在本文中是为 Subject 接口,源码:
package com.defonds.buffer;

public interface Subject {
	public void registerObserver(Observer observer);
	public void removeObserver(Observer observer);
	public void notifyObservers();
}

        《设计模式:可复用面向对象软件的基础》观察者模式中的 Observer 角色,在本文中是为 Observer 接口,源码:
package com.defonds.buffer;

public interface Observer {
	public void update(int onlineNum);
}

        《设计模式:可复用面向对象软件的基础》观察者模式中的 ConcreteSubject 角色,在本文中是为 BufferData 类,源码:
package com.defonds.buffer;

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

public class BufferData implements Subject {
	private int onlinePlayersNum = 0; // store online players num
	private List<Observer> observers = new ArrayList<Observer>(); // refer to all observers
	
	@Override
	public void registerObserver(Observer observer) {
		this.observers.add(observer); // add one observer
		
	}

	@Override
	public void removeObserver(Observer observer) {
		int i = this.observers.indexOf(observer);
		if (i >= 0) {
			this.observers.remove(i);
		}

	}

	@Override
	public void notifyObservers() {
		Iterator<Observer> iterator = this.observers.iterator();
		while (iterator.hasNext()) {
			iterator.next().update(this.onlinePlayersNum);
		}
	}

	public void setOnlinePlayersNum(int onlinePlayersNum) {
		this.onlinePlayersNum = onlinePlayersNum;
		this.notifyObservers();
	}
	
	

}

        《设计模式:可复用面向对象软件的基础》观察者模式中的 ConcreteObserver 角色之一,在本文中是为 PublicDisplay 类,源码:
package com.defonds.buffer;

public class PublicDisplay extends Thread implements Observer, Display {
	private int onlineNum;
	private boolean changed = false;

	@Override
	public void update(int onlineNum) {
		this.onlineNum = onlineNum;
		this.changed = true;
	}
	
	@Override
	public void display() {
		System.out.println("The current number of players online is : " + this.onlineNum);
	}

	@Override
	public void run() {
		while (this.changed) {
			this.display();
			this.changed = false;
		}
	}
}

        《设计模式:可复用面向对象软件的基础》观察者模式中的 ConcreteObserver 角色之二,在本文中是为 InternalDisplay 类,源码:

package com.defonds.buffer;

public class InternalDisplay extends Thread implements Observer, Display {
	private int oldNum = 0;
	private int onlineNum = 0;
	private boolean changed = false;

	@Override
	public void update(int onlineNum) {
		this.oldNum = this.onlineNum;
		this.onlineNum = onlineNum;
		this.changed = true;
	}
	
	@Override
	public void display() {
		System.out.println("The current number of players online is : " + this.onlineNum);
		if(this.onlineNum > this.oldNum) {
			System.out.println("The number of online upward");
		} else {
			System.out.println("The number of online decline");
		}
	}
	
	@Override
	public void run() {
		while (this.changed) {
			this.display();
			this.changed = false;
		}
	}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

从Android ListView 看Observer 观察者设计模式setOnClickListener

这里我不说观察这模式的理论,定义。举例说明我对观察者设计模式的理解。 Android开发中经常用到: mBtn.setOnClickListener(new View.OnClickListener(...
  • zidigua
  • zidigua
  • 2016年12月11日 16:09
  • 330

观察者模式应用场景实例

观察者模式(这个用的太多了)

一.观察者模式的定义 定义对象间一种一对多的依赖关系,是的没当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。 二.观察者模式的使用场景 (1).关联行为场景,需要注意的是,关联行...

观察者模式的优缺点以及使用场景(三)

观察者模式的效果有以下的优点:第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。观察者模式有下面的缺点:第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很...

java:从消息机制谈到观察者模式

观察者模式,顾名思意就是观察与被观察的关系,比如你在烧开水得时时看着它开没开,你就是观察者,开水就是被观察者;再比如说你在带小孩,你关注她是不是饿了,是不是喝了,是不是撒尿了,你就是观察者,小孩就被观...

"围观"设计模式(19)--行为型之观察者模式(Observer Pattern)

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系...

关联规则应用场景实例十则

本文整理了7个天池、DataCastle、CCF中可使用关系分析算法处理的问题场景。 1 穿衣搭配推荐         穿衣搭配是服饰鞋包导购中非常重要的课题,基于搭配专家和达人生成的搭配组合数据,...

酷炫实现WebView与Native完美融合

前言首先看个效果图: 这里背景是native的,左侧边栏也是native的,右侧内容是透明web页面,是不是很酷炫的样子,而且我们还可以自己加蒙版背景,是不是很酷。 这个场景非常适合左侧目录是本地...

现有Android项目引入ReactNative--九步大法

为什么写这篇文章,因为很多时候我们是需要在原Android工程中添加ReactNative,而不是直接react-native init hello来创建工程,而且官网的说明不是很详细,不是完全针对安...

java 设计模式之二-观察者模式

我想玩过魔兽世界的人,在分装备的时候,往往团长手黑就不说了,Roll点也各种悲剧啊.... 这里以roll点为例子,一个团队里的人,分东西的时候,采取Roll点的方法,谁Roll的点高,谁就可以拿装...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式实战应用之二:观察者模式
举报原因:
原因补充:

(最多只允许输入30个字)