Java 设计模式-观察者模式(Observer)

来源:互联网 发布:网约车用什么软件好 编辑:程序博客网 时间:2024/04/29 10:11

写了两个关于设计模式的笔记之后突然感觉上瘾了,我的天啊,原来设计模式这么简单。隐隐约约觉得自己离架构师不远了,好开心,,,

“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都能注册广播接收器,来接受手机系统发出来的消息。

源码下载

0 0
原创粉丝点击