观察者模式(Observer) 又被称"发布-订阅模式"

一:场景说明

记得上初中时,网络还没有现在这么普及,校门口有个小卖部,我常常到哪里订阅报纸,来关心下“天下大事”(当然不止我一个人订阅啦)

如图订阅报纸流程:

订阅报纸的时候常常遇到几个问题?什么时候出版?出版内容是什么?延迟出版怎么办?谁通知我报纸到了?要我去取报纸?还是会有人送过来?等等

把这样的场景带到我们编程世界里来,我们的解决方案之一就是使用观察者设计模式。

二:观察者模式(Observer),定义对象间的一种一对多的依赖关系。当一个对象的状态或内容发生改变时,所有依赖它的对象都得到通知并被自动更新.

观察者模式的结构说明:


三:代码示例:

其实JDK已经实现的Subject和Observer接口的,我们直接可以使用,下面我会介绍的,这里还是先自己实现下,体会下吧


/**
 * 观察者接口
 * 提供通知更新方法 (可以在这个方法中回调目标对象)
 * Created by Administrator on 2016/4/22.
 */
public interface Observer {
    void update(Subject subject);
}



package com.dy.observer;

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


/**
 * 目标对象 ,作为被观察者
 * 它知道观察者,并提供注册和删除观察者
 * Created by Administrator on 2016/4/22.
 */
public class Subject {

    private List<Observer> observerList = new ArrayList<>();

    /**
     * 注册观察者 ,报纸订阅者
     * @param observer
     */
    public void attach(Observer observer){
        observerList.add(observer);
    }

    /**
     * 删除观察者
     * @param observer
     */
    public void detach(Observer observer){
        observerList.remove(observer);
    }

    /**
     * 通知所有观察者
     * 每当报纸被印出来,及时主动通知所有订阅者,好让他们知道
     */
    protected void notifyObserver(){
        for (Observer observer:observerList){
            observer.update(this);
        }
    }
}



package com.dy.observer;

/**
 * 目标对象的继承者
 * 负责具体观察者状态
 * 当自己状态变化,通知所有观察者
 * Created by Administrator on 2016/4/22.
 */
public class NewsPaper extends Subject {
    private String subjectStatus;
    /**
     * 报纸内容
     */
    private String content;

    public String getSubjectStatus() {
        return subjectStatus;
    }


    public void setSubjectStatus(String subjectStatus) {
        this.subjectStatus = subjectStatus;
        //状态改变,通知所有观察者
        this.notifyObserver();
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        //内容有了,说明报纸被印刷出来了,通知所有观察者
        this.notifyObserver();
    }
}



package com.dy.observer;

/**
 * 读者,报纸订阅者
 *
 * 观察者实现类
 * 实现更新方法,使自身状态和目标状态保持一致
 * Created by Administrator on 2016/4/22.
 */
public class Reader implements Observer {


    private String observerStatus;
    private String name;

    public Reader(String name) {
        this.name = name;
    }

    @Override
    public void update(Subject subject) {
        //实现更新方法,使自身状态和目标状态保持一致
        //采用拉的方式
        observerStatus = ((NewsPaper) subject).getSubjectStatus();
        System.out.println(name+"收到了报纸,阅读它,内容是:"+((NewsPaper) subject).getContent());
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



package com.dy.observer;

/**
 * Created by Administrator on 2016/4/22.
 */
public class Client {
    public static void main(String[] args) {

        //报纸被观察者
        NewsPaper newsPager = new NewsPaper();

        //报纸订阅者,也就是观察者
        Reader reader = new Reader("张三");
        Reader reader1 = new Reader("李四");
        Reader reader2 = new Reader("王二");

        //注册订阅者
        newsPager.attach(reader);
        newsPager.attach(reader1);
        newsPager.attach(reader2);

        //印刷出报纸内容
        newsPager.setContent("本期内容介绍观察者模式");
    }
}



客户端测试结果:
张三收到了报纸,阅读它,内容是:本期内容介绍观察者模式
李四收到了报纸,阅读它,内容是:本期内容介绍观察者模式
王二收到了报纸,阅读它,内容是:本期内容介绍观察者模式

Process finished with exit code 0


四:使用jdk实现观察者模式

注意修改对应代码


package com.dy.observer.java;

import java.util.Observable;

/**
 * Created by Administrator on 2016/4/22.
 */
public class NewsPaper extends Observable {

    /**
     * 报纸内容
     */
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
        //内容有了,说明报纸被印刷出来了,通知所有观察者

        //注意JDK的observer模式的时候,下面这句代码不可少
        this.setChanged();
        //主动通知,这里用推的方式
        this.notifyObservers(this.content);
        //如果用的拉的方式,如下代码示例
        //this.notifyObservers();
    }

}



package com.dy.observer.java;


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

/**
 * 读者,报纸订阅者
 *
 * 观察者实现类
 * 实现更新方法,使自身状态和目标状态保持一致
 * Created by Administrator on 2016/4/22.
 */
public class Reader implements Observer {

    private String name;

    public Reader(String name) {
        this.name = name;
    }
    @Override
    public void update(Observable o, Object obj) {
        System.out.println(name+"收到了报纸,目标推过来的内容是:"+obj);
        //拉的方式你自己想想就知道了((NewsPaper) obj).getContent())
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}



public class Client {
    public static void main(String[] args) {

        //报纸被观察者
        NewsPaper jdk_subject = new NewsPaper();

        //报纸订阅者,也就是观察者
        Reader reader = new Reader("张三");
        Reader reader1 = new Reader("李四");
        Reader reader2 = new Reader("王二");

        //注册订阅者
        jdk_subject.addObserver(reader);
        jdk_subject.addObserver(reader1);
        jdk_subject.addObserver(reader2);

        //印刷出报纸内容
        jdk_subject.setContent("本期内容介绍java JDK实现观察者模式");
    }
}



王二收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式
李四收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式
张三收到了报纸,目标推过来的内容是:本期内容介绍java JDK实现观察者模式

Process finished with exit code 0




转载于:https://my.oschina.net/dyyweb/blog/664382

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值