zoukankan      html  css  js  c++  java
  • 设计模式|观察者模式

    观察者模式

    定义:

    定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主体对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新。
    

    例如:朋友圈点赞,这个时候你是观察者,这个信息就是被观察者,也就是主题对象,当这个信息被评论的时候,微信就会通知观察者,不需要你时时刻刻去盯着这个评论;此外,网站的比价降价提醒。

    类型:

    行为型

    适用场景:

    关联行为场景,建立一套触发机制。

    优点:

    观察者和被观察者之间建立一个抽象的耦合。

    观察者模式支持广播通信。

    缺点:

    观察者之间有过多的细节依赖、提高时间消耗及程序复杂度。

    使用要得当,要避免循环调用。

    代码实现:

    实现的场景:在一个网站课程上,同学提出一个问题,讲师监听这个课程的问题。

    有一个课程:

    • Course.java
    package com.design.pattern.behavioral.observer;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:44
     */
    public class Course {
        private String courseName;
    
        public Course(String courseName) {
            this.courseName = courseName;
        }
    
        public String getCourseName() {
            return courseName;
        }
    }
    

    以及问题类:

    • Question.java
    package com.design.pattern.behavioral.observer;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:45
     */
    public class Question {
        private String userName;
        private String questionContent;
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public String getQuestionContent() {
            return questionContent;
        }
    
        public void setQuestionContent(String questionContent) {
            this.questionContent = questionContent;
        }
    }
    

    接下来需要有讲师类:

    • Teacher.java
    package com.design.pattern.behavioral.observer;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:46
     */
    public class Teacher {
        private String teacherName;
    
        public Teacher(String teacherName) {
            this.teacherName = teacherName;
        }
    }
    

    接下来,对于讲师,观察的是这个课程,而不是问题,问题属于课程。

    让课程类继承java的Observable:

    • Course.java
    package com.design.pattern.behavioral.observer;
    
    import java.util.Observable;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:44
     */
    public class Course extends Observable {
        private String courseName;
    
        public Course(String courseName) {
            this.courseName = courseName;
        }
    
        public String getCourseName() {
            return courseName;
        }
    }
    

    让Course可以被观察,在Observable中,添加、删除观察者等方法中使用synchronized修饰,实现线程安全。

    之后,在课程类下创建生产问题的方法,进行通知:

    • Course.java
    package com.design.pattern.behavioral.observer;
    
    import java.util.Observable;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:44
     */
    public class Course extends Observable {
        private String courseName;
    
        public Course(String courseName) {
            this.courseName = courseName;
        }
    
        public String getCourseName() {
            return courseName;
        }
    
        public void produceQuestion(Course course, Question question) {
            System.out.println(question.getUserName() + "在" + course.courseName + "提出了问题。");
            // Observable提供的方法
            setChanged();
            notifyObservers(question);
        }
    }
    

    对于观察者Teacher,需要实现Observer接口:

    • Teacher.java
    package com.design.pattern.behavioral.observer;
    
    import java.util.Observable;
    import java.util.Observer;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 15:46
     */
    public class Teacher implements Observer {
        private String teacherName;
    
        public Teacher(String teacherName) {
            this.teacherName = teacherName;
        }
        @Override
        public void update(Observable o, Object arg) {
            Course course = (Course) o;
            Question question = (Question) arg;
            System.out.println(teacherName + "老师的" + course.getCourseName()
                    + "接收到" + question.getUserName() + "一个问题:" + question.getQuestionContent());
        }
    }
    

    编写测试:

    • Test.java
    package com.design.pattern.behavioral.observer;
    
    /**
     * @Author: JLU Tiger
     * @Date: 2019/9/5 16:01
     */
    public class Test {
        public static void main(String[] args) {
            Course course = new Course("Java设计模式精讲");
            Teacher teacher = new Teacher("Alpha");
            // 添加观察者
            course.addObserver(teacher);
            // 业务逻辑,创建一个问题
            Question question = new Question();
            question.setUserName("Geely");
            question.setQuestionContent("Java的主函数如何编写");
    
            course.produceQuestion(course, question);
        }
    }
    

    运行结果:

    Geely在Java设计模式精讲提出了问题。
    Alpha老师的Java设计模式精讲接收到Geely一个问题:Java的主函数如何编写
    

    此外,对于观察者的update方法的实现,一旦并发过高,现在是同步的,我们需要使用消息队列等异步手段进行更改。

    观察者模式在源码中的应用

    比如我们写一个CS结构的软件,我们添加按钮,在鼠标点击的时候监听这个事件,即事件监听器。例如java.awt.Event,它的实现方式就是观察者模式。
    
    在我们的web开发中,xml的Listener,Listener的上层RequestContextListener实现了ServletRequestListener,而ServletRequestListene又实现了util包下的EventListener接口。
    
    在SpringFrameWork的ReaderEventListener也是继承了EventListener。
  • 相关阅读:
    C# winform 学习(三)
    (Java实现) 均分纸牌
    (Java实现) 拦截导弹
    Delphi从内存流中判断图片格式(好多相关文章)
    Qt之QTableView显示富文本(使用了QAbstractTextDocumentLayout和QTextDocument)
    MAC和PHY的区别(网线上传递的是模拟信号)
    Qt之模型/视图(自定义按钮)(重绘QStyleOptionButton)
    QQ音乐的请求
    Log4j、Log4j 2、Logback、SFL4J、JUL、JCL的比较
    LRU Cache
  • 原文地址:https://www.cnblogs.com/jlutiger/p/11466846.html
Copyright © 2011-2022 走看看