• [设计模式]观察者模式2


    •观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
    这个主题对象在状态上发生变化时,会通知所有观察者对象,让他们能够自动更新自己.

    •观察者模式的组成
    –抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。
    抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现。
    –抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
    –具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
    –具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。
    如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现

    •实现自己的观察者模式

    •观察者模式在Java语言中的地位极其重要
    •JDK也提供了对观察者模式的内置支持

    •Observable类用于创建可以观测到你的程序中其他部分的子类。
    当这种子类的对象发生变化时,观测类被通知。观测类必须实现定义了update( )方法的Observer接口。
    当一个观测程序被通知到一个被观测对象的改变时,update( )方法被调用。

    •一个被观测的对象必须服从下面的两个简单规则。第一,如果它被改变了,它必须调用setChanged( )方法。
    第二,当它准备通知观测程序它的改变时,它必须调用notifyObservers( )方法。
    这导致了在观测对象中对update( )方法的调用。
    注意——当对象在调用notifyObservers( )方法之前,没有调用setChanged( )方法,就不会有什么动作发生。
    在update( )被调用之前,被观测对象必须调用setChanged( )和notifyObservers( )两种方法。

    •注意notifyObservers()有两种形式:一种带有参数而另一种没有。当用参数调用notifyObservers( )方法时,该对象被传给观测程序的update( )方法作为其第二个参数。
    否则,将给update( )方法传递一个null。可以使用第二个参数传递适合于你的应用程序的任何类型的对象。

    •为了观测一个可观测的对象,必须实现Observer接口。这个接口仅仅定义了如下所示的一个方法。
    –void update(Observable observOb, Object arg)
    –这里,observOb是被观测的对象,而arg是由notifyObservers( )方法传递的值。当被观测对象发生了改变,调用update( )方法

    •这里是一个说明可观测对象的例子。该程序创建了一个叫做Watcher的类,该类实现了Observer接口。被监控的类叫做BeingWatched,它继承了Observable。
    在BeingWatched里,是counter( )方法,该方法仅是从一个指定的值开始递减计数。每次计数改变时,notifyObservers( )方法被调用,而当前的计数被作为参数传递给notifyObservers( )方法。
    这导致了Watcher中的update( )方法被调用,显示当前的计数值。在main( )内,分别调用observing和observed的Watcher和BeingWatched对象被创建。
    然后,observing被增加到对observed的观测程序列表。这意味着每次counter( )调用notifyObservers( )方法时,observing.update( )方法将被调用.
    •参见程序 ObserverDemo.java

    •有多个对象可以用作观测程序。例如下面程序实现了两个观测类并且将每个类中的一个对象增加到BeingWatched观测程序列表中。第二个观测程序等待直到计数为0
    •参见程序 TwoObservers.java

    被观察者接口 Watched.java

    1 package cn.itcast.observer1;
    2 
    3 public interface Watched{
    4     public void addWatcher(Watcher watcher);
    5     public void removeWatcher(Watcher watcher);
    6     public void notifyWatchers(String str);
    7 }

    被观察者的具体实现类 ConcreteWatched.java

     1 package cn.itcast.observer1;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 public class ConcreteWatched implements Watched{
     7     private List<Watcher> list = new ArrayList<Watcher>();
     8     
     9     public void addWatcher(Watcher watcher){
    10         list.add(watcher);
    11     }
    12 
    13     public void removeWatcher(Watcher watcher){
    14         list.remove(watcher);
    15     }
    16 
    17     public void notifyWatchers(String str){
    18         for(Watcher watcher : list){
    19             watcher.update(str);
    20         }
    21     }
    22 }

    观察者们要实现的接口(抽象类) Watcher.java

    1 package cn.itcast.observer1;
    2 
    3 public interface Watcher{
    4     public void update(String str);
    5 }

    观察者的具体实现类 ConcreteWatcher.java

    1 package cn.itcast.observer1;
    2 
    3 public class ConcreteWatcher implements Watcher{
    4     public void update(String str){
    5         System.out.println(str);
    6     }
    7 }

    定义两个观察者 TwoObservers.java

     1 package cn.itcast.observer1;
     2 
     3 import java.util.Observable;
     4 import java.util.Observer;
     5 
     6 
     7 class BeingWatched extends Observable{
     8     void counter(int number){
     9         for(;number>=0;number--){
    10             this.setChanged();
    11             //将里面的boolean类型的成员变量由默认false变成了true
    12             this.notifyObservers(number);
    13             //调用这个方法的时候又把成员变量由true变成了false.
    14             //这样下次也是这样不断的去变化.
    15             //这些变化在源代码中体现.
    16             //notifyObservers(number)这个方法中有把装有Observer(watcher)的集合变成一个数组.
    17             // 源代码中for (int i = arrLocal.length-1; i>=0; i--),先遍历最后一个
    18             //所以后边的watcher2先于watcher1执行.
    19         }
    20     }
    21 }
    22 
    23 class Watcher1 implements Observer{
    24     public void update(Observable o, Object arg) {
    25         //这个arg就是上面的this.notifyObservers(number);中的number是Integer类型的
    26         System.out.println("Watcher1's count is:"+arg);
    27     }
    28     
    29 }
    30 class Watcher2 implements Observer{
    31     public void update(Observable o, Object arg) {
    32         //这个地方做一下判断
    33         if(((Integer)arg).intValue()<=5){
    34             System.out.println("Watcher2's count is:"+arg);
    35         }
    36     }
    37 }
    38 public class TwoObservers {
    39     public static void main(String[] args) {
    40         BeingWatched watched =  new BeingWatched();
    41         
    42         Watcher1 watcher1 = new Watcher1();
    43         Watcher2 watcher2 = new Watcher2();
    44         
    45         watched.addObserver(watcher1);
    46         watched.addObserver(watcher2);
    47         
    48         watched.counter(10);
    49     }
    50 }

    Test.java

     1 package cn.itcast.observer1;
     2 
     3 public class Test{
     4     public static void main(String[] args){
     5         Watched girl = new ConcreteWatched();
     6         
     7         Watcher watcher1 = new ConcreteWatcher();
     8         Watcher watcher2 = new ConcreteWatcher();
     9         Watcher watcher3 = new ConcreteWatcher();
    10         
    11         girl.addWatcher(watcher1);
    12         girl.addWatcher(watcher2);
    13         girl.addWatcher(watcher3);
    14         
    15         girl.notifyWatchers("有三个人,高兴");
    16         
    17         girl.removeWatcher(watcher2);
    18         
    19         girl.notifyWatchers("有两个人,不高兴");
    20     }
    21 }
    22     /*
    23     打印内容:
    24     Watcher1's count is:10
    25     Watcher1's count is:9
    26     Watcher1's count is:8
    27     Watcher1's count is:7
    28     Watcher1's count is:6
    29     Watcher2's count is:5
    30     Watcher1's count is:5
    31     Watcher2's count is:4
    32     Watcher1's count is:4
    33     Watcher2's count is:3
    34     Watcher1's count is:3
    35     Watcher2's count is:2
    36     Watcher1's count is:2
    37     Watcher2's count is:1
    38     Watcher1's count is:1
    39     Watcher2's count is:0
    40     Watcher1's count is:0
    41     Watcher2是现执行的,Watcher1是后执行的,原因是
    42     在watched.addObserver()的时候Watcher2是后家进去的,就现执行.
    43     */

     自己浅显的认识:

    在AWT和Swing的事件模型里面几乎全都是使用的观察者模式,

    观察者模式定义了一种一(在AWT中的按钮)对多(多个监听器,按钮被点击的时候多个事件被执行)的依赖关系,
    让多个观察者对象同时监听某一个主题对象(多个监听器监听者这个按钮的变化)。
    这个主题对象在状态上发生变化时(按钮被单击),会通知所有观察者对象,
    让他们能够自动更新自己.

    点击按钮,自动触发触发事件,不是理所当然的,背后是按钮有自动调用事件的机制,

    Button是"主题",在主题中肯定有一个集合存储这些个监听器(或者监听器的引用).
    当你点击这个按钮的时候,就遍历这个集合,找到这个按钮的监听器.
    调用监听器中的ActionPerform方法执行.

    方法肯定是由"主题"来执行的,一定不是自动调用的,看到的自动调用是表面.
    很多框架都用到了观察者模式,而且JDK也认为观察者模式非常的重要,内置了观察者模式的支持API.

    其他模式JDK一般不提供支持,只不过某些类中用到了这个模式,但是观察者模式就不这样,
    甚至提供了类和接口,提供了内在的支持.

  • 相关阅读:
    WebAssembly API & MDN All In One
    Apple iPhone 14 Pro 药丸设计看不懂,药丸上面那条屏幕缝隙完全没有用处呀?
    API 调试工具 All In One
    macOS Time Machine All In One
    使用 macOS 输入多个空格,会自动添加一个点 bug All In One
    手把手的教你如何使用 Vite 搭建一个 React UI 组件库 All In One
    LeetCode 两数相加算法题解 All In One
    如何把 iPad 作为 Mac 扩展屏幕使用 All In One
    【DEMO】【C/C++】最简单的一种回调函数
    Qt中cvMat与QImage,QPixmap的转换
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/4005150.html
Copyright © 2020-2023  润新知