关闭

设计模式 观察者模式 以微信公众服务为例

标签: 设计模式观察者模式
19126人阅读 评论(31) 收藏 举报
分类:

继续设计模式的文章,今天给大家带来观察者模式。

先来看看观察者模式的定义:

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

好了,对于定义的理解总是需要实例来解析的,如今的微信服务号相当火啊,下面就以微信服务号为背景,给大家介绍观察者模式。

看一张图:

其中每个使用者都有上图中的3条线,为了使图片清晰省略了。

如上图所示,服务号就是我们的主题,使用者就是观察者。现在我们明确下功能:

1、服务号就是主题,业务就是推送消息

2、观察者只需要订阅主题,只要有新的消息就会送来

3、当不想要此主题消息时,取消订阅

4、只要服务号还在,就会一直有人订阅

好了,现在我们来看看观察者模式的类图:

接下来就是代码时间了,我们模拟一个微信3D彩票服务号,和一些订阅者。

首先开始写我们的主题接口,和观察者接口:

package com.zhy.pattern.observer;

/**
 * 主题接口,所有的主题必须实现此接口
 * 
 * @author zhy
 * 
 */
public interface Subject
{
	/**
	 * 注册一个观察着
	 * 
	 * @param observer
	 */
	public void registerObserver(Observer observer);

	/**
	 * 移除一个观察者
	 * 
	 * @param observer
	 */
	public void removeObserver(Observer observer);

	/**
	 * 通知所有的观察着
	 */
	public void notifyObservers();

}

package com.zhy.pattern.observer;

/**
 * @author zhy 所有的观察者需要实现此接口
 */
public interface Observer
{
	public void update(String msg);

}

接下来3D服务号的实现类:

package com.zhy.pattern.observer;

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

public class ObjectFor3D implements Subject
{
	private List<Observer> observers = new ArrayList<Observer>();
	/**
	 * 3D彩票的号码
	 */
	private String msg;

	@Override
	public void registerObserver(Observer observer)
	{
		observers.add(observer);
	}

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

	@Override
	public void notifyObservers()
	{
		for (Observer observer : observers)
		{
			observer.update(msg);
		}
	}

	/**
	 * 主题更新消息
	 * 
	 * @param msg
	 */
	public void setMsg(String msg)
	{
		this.msg = msg;
		
		notifyObservers();
	}

}

模拟两个使用者:

package com.zhy.pattern.observer;

public class Observer1 implements Observer
{

	private Subject subject;

	public Observer1(Subject subject)
	{
		this.subject = subject;
		subject.registerObserver(this);
	}

	@Override
	public void update(String msg)
	{
		System.out.println("observer1 得到 3D 号码  -->" + msg + ", 我要记下来。");
	}

}

package com.zhy.pattern.observer;

public class Observer2 implements Observer
{
	private Subject subject ; 
	
	public Observer2(Subject subject)
	{
		this.subject = subject  ;
		subject.registerObserver(this);
	}
	
	@Override
	public void update(String msg)
	{
		System.out.println("observer2 得到 3D 号码 -->" + msg + "我要告诉舍友们。");
	}
	
	

}
可以看出:服务号中维护了所有向它订阅消息的使用者,当服务号有新消息时,通知所有的使用者。整个架构是一种松耦合,主题的实现不依赖与使用者,当增加新的使用者时,主题的代码不需要改变;使用者如何处理得到的数据与主题无关;

最后看下测试代码:

package com.zhy.pattern.observer.test;

import com.zhy.pattern.observer.ObjectFor3D;
import com.zhy.pattern.observer.Observer;
import com.zhy.pattern.observer.Observer1;
import com.zhy.pattern.observer.Observer2;
import com.zhy.pattern.observer.Subject;

public class Test
{
	public static void main(String[] args)
	{
		//模拟一个3D的服务号
		ObjectFor3D subjectFor3d = new ObjectFor3D();
		//客户1
		Observer observer1 = new Observer1(subjectFor3d);
		Observer observer2 = new Observer2(subjectFor3d);

		subjectFor3d.setMsg("20140420的3D号码是:127" );
		subjectFor3d.setMsg("20140421的3D号码是:333" );
		
	}
}

输出结果:
observer1 得到 3D 号码  -->20140420的3D号码是:127, 我要记下来。
observer2 得到 3D 号码 -->20140420的3D号码是:127我要告诉舍友们。
observer1 得到 3D 号码  -->20140421的3D号码是:333, 我要记下来。
observer2 得到 3D 号码 -->20140421的3D号码是:333我要告诉舍友们。

对于JDK或者Andorid中都有很多地方实现了观察者模式,比如XXXView.addXXXListenter , 当然了 XXXView.setOnXXXListener不一定是观察者模式,因为观察者模式是一种一对多的关系,对于setXXXListener是1对1的关系,应该叫回调。

恭喜你学会了观察者模式,上面的观察者模式使我们从无到有的写出,当然了java中已经帮我们实现了观察者模式,借助于java.util.Observable和java.util.Observer。

下面我们使用Java内置的类实现观察者模式:


首先是一个3D彩票服务号主题:

package com.zhy.pattern.observer.java;

import java.util.Observable;

public class SubjectFor3d extends Observable
{
	private String msg ; 
	
	
	public String getMsg()
	{
		return msg;
	}


	/**
	 * 主题更新消息
	 * 
	 * @param msg
	 */
	public void setMsg(String msg)
	{
		this.msg = msg  ;
		setChanged();
		notifyObservers();
	}
}
下面是一个双色球的服务号主题:

package com.zhy.pattern.observer.java;

import java.util.Observable;

public class SubjectForSSQ extends Observable
{
	private String msg ; 
	
	
	public String getMsg()
	{
		return msg;
	}


	/**
	 * 主题更新消息
	 * 
	 * @param msg
	 */
	public void setMsg(String msg)
	{
		this.msg = msg  ;
		setChanged();
		notifyObservers();
	}
}

最后是我们的使用者:

package com.zhy.pattern.observer.java;

import java.util.Observable;
import java.util.Observer;

public class Observer1 implements Observer
{

	public void registerSubject(Observable observable)
	{
		observable.addObserver(this);
	}

	@Override
	public void update(Observable o, Object arg)
	{
		if (o instanceof SubjectFor3d)
		{
			SubjectFor3d subjectFor3d = (SubjectFor3d) o;
			System.out.println("subjectFor3d's msg -- >" + subjectFor3d.getMsg());
		}

		if (o instanceof SubjectForSSQ)
		{
			SubjectForSSQ subjectForSSQ = (SubjectForSSQ) o;
			System.out.println("subjectForSSQ's msg -- >" + subjectForSSQ.getMsg());
		}
	}
}
看一个测试代码:

package com.zhy.pattern.observer.java;

public class Test
{
	public static void main(String[] args)
	{
		SubjectFor3d subjectFor3d = new SubjectFor3d() ;
		SubjectForSSQ subjectForSSQ = new SubjectForSSQ() ;
		
		Observer1 observer1 = new Observer1();
		observer1.registerSubject(subjectFor3d);
		observer1.registerSubject(subjectForSSQ);
		
		
		subjectFor3d.setMsg("hello 3d'nums : 110 ");
		subjectForSSQ.setMsg("ssq'nums : 12,13,31,5,4,3 15");
		
	}
}

测试结果:

subjectFor3d's msg -- >hello 3d'nums : 110 
subjectForSSQ's msg -- >ssq'nums : 12,13,31,5,4,3 15

可以看出,使用Java内置的类实现观察者模式,代码非常简洁,对了addObserver,removeObserver,notifyObservers都已经为我们实现了,所有可以看出Observable(主题)是一个类,而不是一个接口,基本上书上都对于Java的如此设计抱有反面的态度,觉得Java内置的观察者模式,违法了面向接口编程这个原则,但是如果转念想一想,的确你拿一个主题在这写观察者模式(我们自己的实现),接口的思想很好,但是如果现在继续添加很多个主题,每个主题的ddObserver,removeObserver,notifyObservers代码基本都是相同的吧,接口是无法实现代码复用的,而且也没有办法使用组合的模式实现这三个方法的复用,所以我觉得这里把这三个方法在类中实现是合理的。



185
4
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

设计模式(五)观察者模式

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听莫一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们...
  • itachi85
  • itachi85
  • 2016-03-02 17:41
  • 37005

Java设计模式之观察者模式

本文继续介绍23种设计模式系列。介绍的是观察者模式。
  • jason0539
  • jason0539
  • 2015-04-16 07:32
  • 29727

设计模式介绍之七:观察者模式(observer)

观察者模式(又称发布/订阅模式)定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新
  • foruok
  • foruok
  • 2014-02-18 19:55
  • 7298

23种设计模式(8):观察者模式

定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。 类型:行为类模式 类图:         在软件系统中经常会有这样的需求:如果一...
  • zhengzhb
  • zhengzhb
  • 2012-04-18 08:41
  • 33249

深入浅出观察者模式

一、引子还记得警匪片上,匪徒们是怎么配合实施犯罪的吗?一个团伙在进行盗窃的时候,总    有一两个人在门口把风——如果有什么风吹草动,则会立即通知里面的同伙紧急撤退。也许放风的人并不一定认识里面的每一...
  • ai92
  • ai92
  • 2005-05-16 20:01
  • 29515

设计模式读书笔记-----观察者模式

学习设计模式已经有段时间了,这是总结的第一篇博客,文中有错误、漏洞之处,望各位支出,改正。                  ...
  • chenssy
  • chenssy
  • 2013-05-21 15:42
  • 10228

Android设计模式学习之观察者模式

观察者模式在实际项目中使用的也是非常频繁的,它最常用的地方是GUI系统、订阅——发布系统等。因为这个模式的一个重要作用就是解耦,使得它们之间的依赖性更小,甚至做到毫无依赖。以GUI系统来说,应用的UI...
  • u012124438
  • u012124438
  • 2017-02-17 00:25
  • 9720

观察者模式(从放弃到入门)

观察者模式(从放弃到入门)观察者模式从放弃到入门 需求1错误示范 需求2观察者模式 认识观察者模式 需求3Java中自带的观察者模式 思考 源码Observable Observer 解析 一些体会...
  • u013647382
  • u013647382
  • 2016-10-20 10:30
  • 1031

unity里很重要的设计模式 - 观察者模式(Observer)

unity游戏开发里最常用的是 singleton 和 v
  • lynon
  • lynon
  • 2014-06-06 11:16
  • 3939

观察者模式简单例子

观测者模式定义了对象之间的一对多依赖,当一个对象状态发生改变时,其依赖者便会收到通知并做相应的更新。其原则是:为交互对象之间松耦合。以松耦合方式在一系列对象之间沟通状态,我们可以独立复用主题(Subj...
  • qq_15128547
  • qq_15128547
  • 2016-11-17 20:00
  • 2969
    个人资料
    • 访问:17922303次
    • 积分:51373
    • 等级:
    • 排名:第66名
    • 原创:205篇
    • 转载:0篇
    • 译文:6篇
    • 评论:15630条
    我的微信公众号
    联系方式


    QQ群:
    • 55032675
    • 423372824
    • 497438697
    • 请勿重复加群,Thx
    博客专栏
    统计