【设计模式】观察者模式Observer Pattern

时间:2024-02-18 08:10:55

目录

遇到问题

梳理需求

观察者模式的实现

JDK中的实现


遇到问题

当一个对象发生修改时,需要通知多方。

很自然就会想到回调,这个就是观察者模式的核心,观察者模式可以将大量的回调解耦,从而使代码更加优雅。

梳理需求

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

观察者模式的实现

import java.util.ArrayList;
import java.util.List;
 
public class Subject {
   
   private List<Observer> observers 
      = new ArrayList<Observer>();
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
 
   public void attach(Observer observer){
      observers.add(observer);      
   }
 
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}

 接下来定义它的观察者们

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

编写Observer的实现类

public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}
public class OctalObserver extends Observer{
 
   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}
public class HexaObserver extends Observer{
 
   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Hex String: " 
      + Integer.toHexString( subject.getState() ).toUpperCase() ); 
   }
}

使用

public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();
 
      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);
 
      System.out.println("First state change: 15");   
      subject.setState(15);
      System.out.println("Second state change: 10");  
      subject.setState(10);
   }
}

JDK中的实现

Java的JDK中,已经实现观察者模式的相关代码

JDK中提供了Observable抽象类、以及Observer接口

Observable:可被观察的

主要包含两个方法:

setChanged()

每次状态发生变更,都需要手动调用setChanged

如果需要通知观察者,则需要调用

notifyObservers()

注意:如果在调用notifyObservers()方法之前没有调用setChanged()方法,就不会有什么动作发生。

notifyObservers()方法中包含clearChanged()方法,将标志变量置回原值。

notifyObservers()方法采用的是从后向前的遍历方式,即最后加入的观察者最先被调用update()方法。

package com.learnjava.observer;

import java.util.Observable;
import java.util.Observer;

class WatchedCounter extends Observable
{
    public void countdown(int number)
    {
        for (; number >= 0; --number)
        {
            // 设置改变变量
            setChanged();

            // 通知所有观察者,将number作为参数信息传递给观察者
            notifyObservers(number);

        }

    }
}

class Watcher1 implements Observer
{
    @Override
    public void update(Observable arg0, Object arg1)
    {
        System.out.println("Watcher1's number: " + arg1);

    }
}

class Watcher2 implements Observer
{
    @Override
    public void update(Observable arg0, Object arg1)
    {

        if (((Integer) arg1).intValue() <= 5)
        {
            System.out.println("Watcher2's number: " + arg1);
        }
    }
}

public class ObserverTest
{
    public static void main(String[] args)
    {
        WatchedCounter watchedCounter = new WatchedCounter();
        Watcher1 watcher1 = new Watcher1();
        Watcher2 watcher2 = new Watcher2();

        //添加观察者
        watchedCounter.addObserver(watcher1);
        watchedCounter.addObserver(watcher2);

        //开始倒数计数
        watchedCounter.countdown(10);
    }

}