用Java设计模式中的观察者模式开发微信公众号的例子
还记得警匪片上,匪徒们是怎么配合实施犯罪的吗?一个团伙在进行盗窃的时候,总有一两个人在门口把风——如果有什么风吹草动,则会立即通知里面的同伙紧急撤退。也许放风的人并不一定认识里面的每一个同伙;而在里面也许有新来的小弟不认识这个放风的。但是这没什么,这个影响不了他们之间的通讯,因为他们之间有早已商定好的暗号。
呵呵,上面提到的放风者、偷窃者之间的关系就是观察者模式在现实中的活生生的例子。
观察者(observer)模式又名发布-订阅(publish/subscribe)模式。gof给观察者模式如下定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在这里先讲一下面向对象设计的一个重要原则——单一职责原则。因此系统的每个对象应该将重点放在问题域中的离散抽象上。因此理想的情况下,一个对象只做一件事情。这样在开发中也就带来了诸多的好处:提供了重用性和维护性,也是进行重构的良好的基础。
因此几乎所有的设计模式都是基于这个基本的设计原则来的。观察者模式的起源我觉得应该是在gui和业务数据的处理上,因为现在绝大多数讲解观察者模式的例子都是这一题材。但是观察者模式的应用决不仅限于此一方面。
好了,对于定义的理解总是需要实例来解析的,如今的微信服务号相当火啊,下面就以微信服务号为背景,给大家介绍观察者模式。
看一张图:
其中每个使用者都有上图中的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代码基本都是相同的吧,接口是无法实现代码复用的,而且也没有办法使用组合的模式实现这三个方法的复用,所以我觉得这里把这三个方法在类中实现是合理的。
下一篇: php 7新特性之类型申明详解
推荐阅读
-
用Java设计模式中的观察者模式开发微信公众号的例子
-
用Java设计模式中的观察者模式开发微信公众号的例子
-
在微信开发模式中,关于‘’该公众号暂时无法提供服务,请稍后再试“的问题
-
微信公众号编辑模式与开发模式的区别介绍
-
在开发微信订阅号时,要如何在开发模式下编辑图文;例如在文章中插入图片等编辑模式的功能?
-
在微信开发模式中,关于‘’该公众号暂时无法提供服务,请稍后再试“的问题
-
在开发微信订阅号时,要如何在开发模式下编辑图文;例如在文章中插入图片等编辑模式的功能?
-
用Java设计模式中的观察者模式开发微信公众号的实例代码
-
详解java微信企业号开发之开发模式的开启步骤
-
微信公众号编辑模式与开发模式的区别介绍