写了两个关于设计模式的笔记之后突然感觉上瘾了,我的天啊,原来设计模式这么简单。隐隐约约觉得自己离架构师不远了,好开心,,,
“Ruffian,Ruffian,快醒醒,怎么博客写一半就睡着了,,,”。卧槽,是梦,是梦,,,
好吧,被叫醒了,那还是继续写博客吧。
今天记录一下观察这模式。先看看定义
观察这模式:对象间的一种一对多的依赖关系,一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
诶,这个定义不错,简单明了,看字面意思就理解的差不多了,个人觉得还是有点抽象。
嗯,那么举个贴切生活的例子,微信公众号(CSDN大神鸿洋也曾使用这个来举例说明观察者模式,这里不排除笔者有抄袭的嫌疑,哈哈,不过对比网上这么多例子,还是觉得这个贴切,那就拿微信公众号来举例子说明 观察者模式 吧)
在互联网迅速发展的今天,微信这个大平台似乎成了一些商户宣传和推广自己产品的好渠道,例如深圳华强北某手机商户,开发了一个微信公众号,每天推送自己的新品手机,手机爱好者通过订阅公众号,可以接收到商户推送的消息,当然,哪天不喜欢了,就可以取消关注。
结合定义,
对象间的一种一对多的依赖关系
微信公众号跟关注者(手机爱好者)是一种一对多的关系
一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新
公众号推送了一条关于新品手机的消息,(一个对象发生了变化) ,关注者(依赖它的对象)就可以接收到推送过来的消息(都得到通知并自动刷新)。
观察者模式的定义真的很容易理解,特别结合微信公众号这个例子,如果你这都理解不了?卧槽,这都理解不了,那就只能通过代码来看看能不能帮到你了
首先创建一个微信公众号抽象类(主题类),不同类型的公众号从这里继承,然后各自实现自己的业务,然后创建一个观察者接口,所有的观察者实现这个接口。
主题类(公众号抽象类)
package cn.design.java.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 公众号抽象类<br/>
* 所有公众号继承此类
*
* @author Ruffian
* @date 2016年5月13日
*
*/
public abstract class Subject {
// 保存注册的观察者(保存所有关注公众号的用户)
private List<Observer> observers = new ArrayList<Observer>();
// 注册观察者(关注公众号)
public void attach(Observer observer) {
observers.add(observer);
}
// 删除观察者(取消关注)
public void detach(Observer observer) {
observers.remove(observer);
}
// 通知所有注册的观察者(推送消息给用户)
public void nodifyObservers() {
for (Observer observer : observers) {
observer.update(this);
}
}
}
观察者(接口)
package cn.design.java.observer;
/**
* 观察者接口<br/>
* 所有观察者实现此接口
*
* @author Ruffian
* @date 2016年5月13日
*
*/
public interface Observer {
/**
* 更新接口
*
* @param msg
* @author Ruffian
* @date 2016年5月13日
*/
public void update(Subject subject);
}
仔细看代码,注释的很详细了。接下来我们创建一个具体主题的实现类(手机市场公众号),创建2个观察者具体实现类(手机爱好者),代码只是为了只管体现1对多的模式,不要太在意逻辑(这里我纯粹copy了一下)
具体主题的实现类(手机市场公众号)
package cn.design.java.observer;
/**
* 主题实现类<br/>
* 某个手机行业相关的公众号
*
* @author Ruffian
* @date 2016年5月13日
*
*/
public class PhoneSubject extends Subject {
private double price;
private String phone;
// 设置推送信息(手机型号,价格)
public void setPhoneMsg(String phone, double price) {
this.phone = phone;
this.price = price;
}
// 获取推送信息
public String getPhoneMsg() {
return "手机型号:" + phone + ",价格:" + price;
}
// 推送内容
public void pushPhone() {
System.out.println("公众号推送:" + getPhoneMsg());
// 通知观察者
nodifyObservers();
}
}
观察者具体实现类(手机爱好者)
package cn.design.java.observer;
/**
* 观察者实现类<br/>
* 手机爱好者
*
* @author Ruffian
* @date 2016年5月13日
*
*/
public class PhoneFans1Observer implements Observer {
@Override
public void update(Subject subject) {
// 接收到公众号推送的消息
/**
* update(Subject subject) <br/>
* 备注: 参数可以设置为具体的消息(String),或者 Subject对象<br/>
* 1.String:直接展示推送过来的消息 <br/>
* 2.Subject:如果是Subject对象,则从Subject对象中获取需要的内容
*/
String phoneMsg = ((PhoneSubject) subject).getPhoneMsg();
// 展示消息
System.out.println("粉丝1收到消息:" + phoneMsg);
}
}
package cn.design.java.observer;
/**
* 观察者实现类<br/>
* 手机爱好者
*
* @author Ruffian
* @date 2016年5月13日
*
*/
public class PhoneFans2Observer implements Observer {
@Override
public void update(Subject subject) {
// 接收到公众号推送的消息
/**
* update(Subject subject) <br/>
* 备注: 参数可以设置为具体的消息(String),或者 Subject对象<br/>
* 1.String:直接展示推送过来的消息 <br/>
* 2.Subject:如果是Subject对象,则从Subject对象中获取需要的内容
*/
String phoneMsg = ((PhoneSubject) subject).getPhoneMsg();
// 展示消息
System.out.println("粉丝2收到消息:" + phoneMsg);
}
}
订阅者实现类创建了2个,公众号创建了1个,现在两个订阅者去订阅公众号,那么当公众号推送手机新品的时候,所有的订阅者都能接收到来自公众号的推送消息。
测试类
package cn.design.java.observer;
public class Test {
public static void main(String[] args) {
PhoneSubject subject = new PhoneSubject();
Observer phoneFans1 = new PhoneFans1Observer();
Observer phoneFans2 = new PhoneFans2Observer();
// 手机爱好者关注公众号
subject.attach(phoneFans1);
subject.attach(phoneFans2);
// 公众号编辑要推送的消息
subject.setPhoneMsg("iPhone6s", 5288);
// 推送消息
subject.pushPhone();
}
}
结果打印
卧槽,这么简单明了的例子,要说的话在代码注释了都写完了,真不知道还能说些啥。看看代码吧。
看到这里Android开发者们有没有想到这个模式在安卓中哪里有用到呢?哎呀职业病,总是会想在Android哪里有运用。想到了吗?
没错就是广播!系统某个广播(例如手机开机启动广播),所有的APP都能注册广播接收器,来接受手机系统发出来的消息。