zoukankan      html  css  js  c++  java
  • java常用设计模式(三)观察者模式

      设计模式第三篇,观察者模式,大家多多指教

    简介

      观察者模式定义了对象之间的一组一对多的依赖,当一个对象改变时,其他被依赖的对象都会收到通知并且自动更新(引自《Head First设计模式》)。首先观察者模式有一个对象,我们称之为主题对象(Subject),有很多其他的对象我们称之为观察者(Observer),主题对象和观察者是一对多的关系,当主题对象发生改变时,观察者会收到来自于主题对象的通知,并根据通知做出相应的操作。在这里有一个需要注意的地方,那就是一个对象要成为观察者或者不想做观察者了,都需要告知主题对象,主题对象会更新一对多的这个依赖关系,由此可见主题对象应该维护的有一个观察者列表。

    JDK内置的观察者模式

      JAVA API内置的观察者模式分别是java.util.Observable类和java.util.Observable接口。要实现观察者模式只需要把主题对象继承java.util.Observable类,把观察者实现java.util.Observable接口。下面我们通过一个例子来展示观察者模式的工作过程,例子的场景是某个社区提问的过程:

      第一步:新建一个问题类,定义两个成员变量分别是提问人和问题的内容

    /*
     * 问题
     */
    public class Question {
        /** 提问人 */
        private String name;
        /** 问题内容 */
        private String question;
    
        public Question(String name, String question) {
            this.name = name;
            this.question = question;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getQuestion() {
            return question;
        }
    
        public void setQuestion(String question) {
            this.question = question;
        }
    }

      第二步:新建主体对象,此处的主体对象应该是社区,社区类继承Observable类,提问方法是publishQuestion,此处会设置主体对象为已改变,并且通知所有的观察者

    /*
     * 社区对象
     */
    public class Community extends Observable {
        private static Community community;
    
        private Community(){
            if(community != null){
                throw new RuntimeException("不要想反射攻击我");
            }
        }
    
        public static Community getInstance(){
            if(community == null){
                community = new Community();
            }
            return community;
        }
    
        public void publishQuestion(Question question){
            System.out.println(question.getName()+"在社区提了提了一个问题,问题内容是:"+ question.getQuestion());
            /** 设置主体对象的状态为已改变 */
            setChanged();
            /** 通知所有的观察者 */
            notifyObservers(question);
        }
    }

      第三步:新建观察者为社区的工作人员,负责解决问题,观察者要实现Observer接口

    public class Worker implements Observer {
    
        @Override
        public void update(Observable o, Object arg) {
            Community community = (Community) o;
            Question question = (Question) arg;
    
            System.out.println("==================");
            System.out.println("收到来自社区的一个提问,提问人是:"+ question.getName());
            System.out.println("内容是:"+ question.getQuestion());
        }
    }

       第四步:注册观察者,把观察者和主题对象关联起来

    public class ObserverTest {
    
        public static void main(String[] args) {
            Community community = Community.getInstance();
            Question question = new Question("张三","几点上班?");
            /** 观察者注册 */
            community.addObserver(new Worker());
            community.publishQuestion(question);
        }
    
    }

    番外

      上面的观察者模式的实现是由主题对象往观察者去“推消息“,即主题对象主动去通知观察者(Community去通知Worker) ,其实这种java API还支持观察者去主题对象去“拉消息”,这种做法和推各有特点,推的好处是由主题对象去控制推的时机和内容,能够一次性把所有的东西推给观察者,但是对于不同的观察者而言有种一视同仁的感觉,如果所有观察者需要的信息并不一致的话,就需要去推更多的内容,这其中必定包含一些冗余的消息。拉的好处是能够由观察者自主的去选择需要的内容和时机,这样观察者能够只拉自己想要的东西,而且由于时间又观察者定,主题对象和观察者之间的交互就不会有那么频繁,但是这样的话主题对象必须把自己“暴露”给观察者,而且收集到的信息可能不全,需要多次收集才能补全。(目前主流的做法是推) 

    总结

      jdk自带的观察者模式实现了主题对象和观察者之前的松耦合,定义了对象之间的一对多的关系,主题对象不需要知道观察者的细节,也不需要知道到底谁成为了观察者。jdk自带的观察者模式是使用继承的方式去实现,一定程度上违背的OO设计的原则:多用组合,少用继承,而且继承带来的问题必然是扩展的麻烦。Observable类其实是比较简单的,它的源码主要就是两个成员变量和几个方法,如果有必要的话,可以实现自己的Observable,希望各位小伙伴都能掌握松耦合的设计思想。

  • 相关阅读:
    the core or essence of a computer
    HEXADECIMAL NOTATION is Syntactic_sugar.
    Converting from Decimal Notation to Binary Notation for Fractions
    convert from base 10 to base 2
    MYSQL PASSWORD()
    Environment Variables
    Why Stored Procedures?
    delimiter
    page fault rate
    Segmentation
  • 原文地址:https://www.cnblogs.com/blue-and-white/p/11066111.html
Copyright © 2011-2022 走看看