微信订阅号项目中观察者模式解析
一、什么是观察者模式
1、生活中的观察者模式
警察抓小偷
在现实生活中,警察抓小偷是一个典型的观察者模式「这以一个惯犯在街道逛街然后被抓为例子」,这里小偷就是被观察者,各个干警就是观察者,干警时时观察着小偷,当小偷正在偷东西「就给干警发送出一条信号,实际上小偷不可能告诉干警我有偷东西」,干警收到信号,出击抓小偷。这就是一个观察者模式
装模作样写作业
小时候家里家活比较多,爸妈让我去干活的时候,我偶尔会说我要学习「其实不想去干活,当然只是偶尔,我还是常常干家务的」,然后爸妈就去地里了,我一个人在家里,先摆出一张桌子「上面放好想看的书」,然后打开电视机看起电视剧,但是又怕家里人回到家中看到我在看电视,于是把家里的大门锁住「当爸妈回的时候肯定要开门」,当我听见开门声就会立马关掉电视,做到作业桌上「装模作样写作业」----在这过程中:我充当的就是观察者,爸妈就是被观察者,他们开门就会触发门响「相当于告诉我说他们回来了」,我听到响声「关电视,写作业」,有过类似的经验的朋友们下面点个赞
远程视频会议
老板和员工远程开会:老板是被观察者,员工是观察者。微信公号:微信公号作者是被观察者,微信用户是观察者「当公号作者发送一篇文章,关注了公号的观察者都可以收到文章」等
2、程序中的观察者模式
观察者模式的定义
观察者模式描述的是一种一对多的关系「一个被观察者对应多个观察者」,当被观察者的状态发生改变时,所有观察者都会得到通知。通俗的理解:观察者模式就是在特定的时刻「被观察者发送通知」干特定的事情「观察者收到通知处理自己相应的事件」
观察者模式的特点
观察者模式的三要素:观察者,被观察者,事件「订阅」
观察者模式的结构
角色 | 类别 | 说明 |
---|---|---|
Subject | 接口或抽象类 | 主题也叫被观察者 |
RealSubject | 真实的主题类 | 具体的被观察者,内部维护了观察者的列表 |
IObserver | 观察者接口或抽象类 | 抽象出观察者的接口 |
RealObserver | 具体的观察者 | 被观察者有更新,观察者立马响应更新 |
二、观察者模式在微信订阅号中的应用
在微信的订阅号中,订阅号可以被关注或取消关注,当有新的文章、消息、出现的时候,订阅了的读者都会收到消息。所以可以抽象出来一个共同的抽象类Publisher
来实现这些公共的方法。
1 public abstract class Publisher { 2 private List<Subscriber> funs = new ArrayList<Subscriber>(); 3 private String message; 4 5 public void publishMessage(String message) { 6 this.message = message; 7 notifyAllSubscribers(); 8 } 9 10 public String getMessage() { 11 return message; 12 } 13 14 public void addSubscriber(Subscriber subscriber) { 15 funs.add(subscriber); 16 } 17 public void delSubscriber(Subscriber subscriber) { 18 funs.remove(subscriber); 19 } 20 public void notifyAllSubscribers() { 21 Iterator<Subscriber> it = funs.iterator(); 22 while (it.hasNext()) { 23 it.next().update(this); 24 } 25 } 26 }
Publisher
维护有一个订阅者的集合,其中message
统一表示文章、信息或声音作品等各种形式的内容,由publishMessage
更新内容,而当有新的内容更新时,会调用notifyAllSubscibers
方法来通知所有关注人。这里要注意的是,这种通知是一种回调行为,也就是通过遍历并调用各个subscriber
的update
方法来进行通知。
1 public interface Subscriber { 2 void update(Publisher publisher); 3 }
因此,具体来说,微信订阅号就是一种Publisher。
1 public class WeixinPublisher extends Publisher { 2 private String dingyuehao; 3 4 public WeixinPublisher(String dingyuehao) { 5 this.dingyuehao = dingyuehao; 6 } 7 8 @Override 9 public String toString() { 10 return "微信订阅号[" + dingyuehao + "]"; 11 } 12 }
而普通的微信用户——即关注者——就是Subscriber。
1 public class WeixinAccount implements Subscriber { 2 private String accountName; 3 4 public WeixinAccount(String accountName) { 5 this.accountName = accountName; 6 } 7 8 public void update(Publisher publisher) { 9 System.out.println(accountName + "的微信收到了来自" + publisher + "的推送文章: " + publisher.getMessage()); 10 } 11 }
微信用户实现了具体的update方法,定义了在收到通知后要做哪些操作,比如阅读、转发等等,这里通过打印一行文字来表示。
1 public class Client { 2 public static void main(String[] args) { 3 WeixinPublisher publisher = new WeixinPublisher("享学IT"); 4 publisher.addSubscriber(new WeixinAccount("张三")); 5 publisher.addSubscriber(new WeixinAccount("李四")); 6 publisher.addSubscriber(new WeixinAccount("王五")); 7 8 publisher.publishMessage("Java设计模式百例-观察者模式"); 9 } 10 }
例如,张三执行“关注”操作后,微信订阅号执行addSubscriber操作将他添加到自己的订阅者名单中,当发布新消息时,订阅者都可以收到,输出如下。
张三的微信收到了来自微信订阅号[享学IT]的推送文章: Java设计模式百例-观察者模式
三、观察者模式的优缺点
1、优点
1、解耦,被观察者只知道观察者列表「抽象接口」,被观察者不知道具体的观察者
2、被观察者发送通知,所有注册的观察者都会收到信息「可以实现广播机制」
2、缺点
1、如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
2、观察者知道被观察者发送通知了,但是观察者不知道所观察的对象具体是如何发生变化的
3、如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃