zoukankan      html  css  js  c++  java
  • 《图解设计模式》读书笔记8-1 Observer模式

    Observer模式即观察者模式,该模式中,被观察者的状态发生变化后会通知给观察者。

    此模式适用于根据对象状态进行处理的场景。

    示例程序

    下面代码的功能是:被观察者是一个随机数生成器,有两个观察者,分别以数值形式和图示形式展示被观察者生成的数字。

    程序类图

    程序

    抽象的数字生成器

    public abstract class NumberGenerator {
        //观察者列表
        private ArrayList observers = new ArrayList();
        //增加观察者
        public void addObserver(Observer observer) {   
            observers.add(observer);
        }
        //删除观察者
        public void deleteObserver(Observer observer) {
            observers.remove(observer);
        }
        //提醒观察者
        public void notifyObservers() {               
            Iterator it = observers.iterator();
            while (it.hasNext()) {
                Observer o = (Observer)it.next();
                o.update(this);
            }
        }
        public abstract int getNumber();               
        public abstract void execute();                
    }
    

    具体的数字生成器

    执行execute()方法后通知观察者

    public class RandomNumberGenerator extends NumberGenerator {
        private Random random = new Random();   
        private int number;                     
        public int getNumber() {                
            return number;
        }
        public void execute() {
            for (int i = 0; i < 20; i++) {
                number = random.nextInt(50);
                notifyObservers();
            }
        }
    }
    

    观察者接口

    public interface Observer {
        void update(NumberGenerator generator);
    }
    

    观察者(数字形式展示)

    public class DigitObserver implements Observer {
        public void update(NumberGenerator generator) {
            System.out.println("DigitObserver:" + generator.getNumber());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }
    

    观察者(图形方式展示)

    public class GraphObserver implements Observer {
        public void update(NumberGenerator generator) {
            System.out.print("GraphObserver:");
            int count = generator.getNumber();
            for (int i = 0; i < count; i++) {
                System.out.print("*");
            }
            System.out.println("");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }
    

    执行

    public class Main {
        public static void main(String[] args) {
            NumberGenerator generator = new RandomNumberGenerator();
            Observer observer1 = new DigitObserver();
            Observer observer2 = new GraphObserver();
            generator.addObserver(observer1);
            generator.addObserver(observer2);
            generator.execute();
        }
    }
    
    //结果
    DigitObserver:22
    GraphObserver:**********************
    DigitObserver:11
    GraphObserver:***********
    DigitObserver:40
    GraphObserver:****************************************
    DigitObserver:39
    GraphObserver:***************************************
    DigitObserver:28
    GraphObserver:****************************
    DigitObserver:23
    GraphObserver:***********************
    DigitObserver:38
    GraphObserver:**************************************
    DigitObserver:39
    GraphObserver:***************************************
    ......省略
    

    角色和类图

    角色

    • Subject:被观察者

    被观察者内部维护了一个观察者的list,定义了增加和删除观察者的方法。同时还定义了一个通知观察者的方法,作用是:如果自己内部发生了变化,通知观察者取得这些变化。本例中由NumberGenerator扮演这个角色。

    • ConcreteSubject:具体的被观察者

    实现了被观察者的执行方法,在执行过程中调用方法通知观察者。本例中由RandomNumberGenerator扮演此角色。

    • Observer:观察者

    声明供被观察者调用的方法,此方法可以获得被观察者状态的变化值。本例中由Observer接口扮演此角色。

    • ConcreteObserver:具体的观察者

    实现了观察者接口的方法,通过这个方法可以获得被观察者的值,达到监控的目的。本例中由DigitObserverGraphObserver扮演此角色。

    类图

    思路拓展

    可复用性

    对于具体的被观察者和观察者而言,他们之间的关系由他们的父类和接口进行关联。

    具体的被观察者RandomNumberGenerator不需要知道观察者是谁,有多少,它只负责执行时调用通知方法通知观察者即可。

    具体的观察者GraphObserverDigitObserver不需要知道是谁实现了NumberGenerator,只负责拿到值并处理即可。

    这样的设计降低了耦合度,提升组件可复用性。其做法的特点是:

    利用抽象类和接口从具体类中抽出抽象方法。

    将实例作为参数传递至类中,或者在类的字段中保存实例时,不使用具体类型,而是使用抽象类型和接口。

    Observer的顺序

    如果观察者能够改变被观察者的数据,那就要注意观察者的调用顺序了。还要注意防止循环调用

    当Subject发生变化时,通知Observer,Observer改变Subject,Subject发生变化,通知Observer...

    MVC模式

    Model发生改变时通知View,View根据Model的值显示新的内容。Model就是被观察者,View就是观察者。

  • 相关阅读:
    OPENSSL库使用--AES篇
    Linux inotify功能及实现原理
    LSI RAID
    Linux下关于热插拔硬盘的指令
    最长回文字串理解(学习Manacher's algorithm)
    pat 1068 动态规划/Fina More Conis
    (二)Myeclipse中关于jdk配置,解决版本不一致问题
    (一)MyEclipse配置Tomcat,与jsp程序运行
    pat 1047 解题心得
    pat 1038 Smallest Number解题心得
  • 原文地址:https://www.cnblogs.com/qianbixin/p/11144636.html
Copyright © 2011-2022 走看看