设计模式学习笔记-观察者模式

来源:互联网 发布:端口辅助是什么意思 编辑:程序博客网 时间:2024/06/01 10:44

1.概述

    有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

2.所能解决的问题

    将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。

3. 模式中的角色

  1. 抽象主题(Subject):
    它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  2. 具体主题(ConcreteSubject):
    将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  3. 抽象观察者(Observer):
    为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

  4. 具体观察者(ConcreteObserver):
    实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。


这是重点

4.观察者模式简单理解(个人理解)

从生活中理解(有点长~担待~文笔不好~)

如果大家记得的话,高中时候每个班级里面都会有一个喇叭,不管是听英语听力,还是学校广播新闻,通报批评某某某(个人就干过这种事~~~丢人).
从学校广播室发出—>然后各班级接受到—->学生做出相应的反应;

这个广播呢是由校领导发出,所以校领导 ====== 抽象的主题
话筒是代表校领导的具体,所以话筒 ====== 观察者.
教室装着学生, 所以教学 ====== 抽象观察者
那么学生,就是接受消息,做反应的. 所以学生 ======= 具体观察者

上面的可以理解,基本上就大概知道我想要表达的意思了吧.

1.某天校领导,决定了一件事情之后,想要通知学生,但又并不一定是全部学生,所以让人去话筒那 (校领导总是那么的懒) ,1.1对着喇叭喊话:没有交学费的抓紧时间交学费~~ ~~ 然后呢,校长就有钱了,可以找大学生了 ~~~ 1.2 亦或者是同志学生全体下来做广播体操(这是最痛恨的~)

2.某天呢,门卫想要借用下喇叭,怎么办呢, 换一个主题呗,总不能跑到校领导办公室喊一嗓子.然后呢门卫那就有了一个话筒. 对着喇叭喊话: 马蓉~~~ 宋喆拿着两瓶旺仔牛奶在学校门口等着!!! 然后呢,就屁颠屁颠过去学校门口了,一口干下,瞬间躺地不起~

主题中有所有希望接受消息的观察者的引用,主题的状态更改,观察者接受消息,做出相应的反馈.这就是观察者模式. 

使具体主题和具体观察者的耦合解除,让双方都依赖于抽象,而不是依赖于具体的对象从而使得各自的变化都不会影响另一边的变化。

从Android的BroadcastReceiver(广播)来解读

  1. 抽象观察者 ====== BroadcastReceiver
  2. 具体观察者 ====== class Receiver extends BroadcastReceiver
  3. 抽象主题 ====== AndroidManifest.xml
  4. 具体主题 ====== Intent 的action 或者中的action

每一个广播接收器(具体观察者)都需要实现一个接口BroadcastReceiver(抽象观察者) 并在AndroidManifest.xml (抽象主题)中注册,最终由Activity或者其他来发送相应的广播,感兴趣的观察者,介绍到相应的Action做出相应的响应~

个人的一些见解,不知道是否正确,如有错误希望大家指出~


5.代码

模拟一个求职 ,一个海龟,一个大学生,发送求职简历,之后公司发布职位公告,相应专业过去面试

抽象主题 subject.java

/** * TODO  主题, * 1.添加观察者 * 2.删除观察者 * 3.通知观察者 * 4.发送消息 * */public interface Subject {    public void addObserver(Observer o);    public void deleteObserver(Observer o);    public void notifyObserver();    public void giveNewMess(String mess);}

具体主题SeekJobCenter.java

/** * TODO  具体主题 * 1.需要发送的消息 * 2.是否发送消息flag * 3.观察者的集合List<观察者> * */public class SeekJobCenter implements Subject{    String mess;    boolean changed;    List<Observer> personList;    public SeekJobCenter() {        personList = new ArrayList<Observer>();        mess = "";        changed =false;    }    @Override    public void addObserver(Observer o) {        if (!personList.contains(o)) {            personList.add(o);        }    }    @Override    public void deleteObserver(Observer o) {        if (personList.contains(o)) {            personList.remove(o);        }    }    @Override    public void notifyObserver() {        if (changed) {            for (int i = 0; i < personList.size(); i++) {                Observer observer = personList.get(i);                observer.hearTelephone(mess);            }            changed = false;        }    }    @Override    public void giveNewMess(String mess) {        if (mess.equals(this.mess)) {            changed = false;        }        else {            this.mess = mess;            changed = true;        }    }}

抽象观察者Observer .java

/** *  * TODO 抽象观察者 * 接听消息 * */public interface Observer {    public void hearTelephone(String hearMess);}

具体观察者

HaiGui.java

/** *  * TODO  具体观察者 * 1.抽象观察者的引用 * 2.文件 * */public class HaiGui implements Observer{    Subject subject;    File myFile;    public HaiGui(Subject subject ,String fileName) {        this.subject = subject;        subject.addObserver(this);        this.myFile = new File(fileName);    }    @Override    public void hearTelephone(String heardMess) {        try {            boolean boo = heardMess.contains("程序员")||heardMess.contains("软件");            if (boo) {                FileOutputStream out = new FileOutputStream(myFile,true);                byte[] b = heardMess.getBytes();                out.write(b);                System.out.println("我是一名海龟");                out.close();            }            else {                System.out.println("沒有海龟需要的信息!");            }        } catch (Exception e) {            System.out.println(e.toString());        }    }}

UniversityStudent.java

/** *  * TODO  具体观察者 * */public class UniversityStudent implements Observer{    Subject subject;    File myFile;    public UniversityStudent(Subject subject ,String fileName) {        this.subject = subject;        subject.addObserver(this);        this.myFile = new File(fileName);    }    @Override    public void hearTelephone(String heardMess) {        try {            System.out.println("@@@@@@@@@@@@");            FileOutputStream out = new FileOutputStream(myFile,true);            byte[] b = heardMess.getBytes();            out.write(b);            System.out.println("我是一名大学生");            out.close();                        } catch (Exception e) {            System.out.println(e.toString());        }    }    }

测试 Application.java

public class Test {    public static void main(String[] args) {        Subject center = new SeekJobCenter();        Observer zhang = new UniversityStudent(center, "A.txt");        Observer wang = new HaiGui(center, "a12.txt");        center.giveNewMess("IBM公司需要java程序员");        center.notifyObserver();        center.giveNewMess("北京图书大厦需要管理员");        center.notifyObserver();        center.giveNewMess("马世豪需要招聘软件教师");        center.notifyObserver();        center.giveNewMess("马世豪");        center.notifyObserver();    }}

6.观察模式总结

  1. 优点
    观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
  2. 缺点依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
  3. 适用场景
    1.当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
    2.一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

源码下载

1 0
原创粉丝点击