观察者模式

160 阅读2分钟

背景

在 Observer 模式中,当观察对象的状态发生变化时,会通知观察者。Observer模式适用于根据对象状态进行相应处理的场景

登场角色

Observer 观察者

Observer 角色负责 接收 来自subject角色的状态变化的通知,声明了update的抽象方法

ConcreteObserver 具体的观察者

表示具体的Observer,当update方法调用时,就要去获取被观察者的最新状态;

Subject 观察对象

表示被观察的对象,里面定义并实现了注册移除唤醒观察者的方法,它还声明了“获取现在的状态”的方法;

ConcreteSubject 具体的观察对象

表示具体的被观察的对象,当自身状态发生变化后,它会通知所有已经注册了的观察者;

类图

示例代码

例子为当被观察者获取了一个新的随机数后,就会唤醒所有的Observer,调用他们的update方法,然后把它们打印出来

Subject 被观察者

public abstract class NumberGenerator {
    /**
     * 保存观察者
     */
    private ArrayList<Observer> observers = new ArrayList<>();

    /**
     * 添加观察者
     * @param observer
     */
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    /**
     * 移除观察者
     * @param observer
     */
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 唤醒所有观察者
     */
    public void notifyObservers() {
        Iterator<Observer> iterator = observers.iterator();
        while (iterator.hasNext()) {
            Observer observer = iterator.next();
            observer.update(this);
        }
    }

    /**
     * 执行方法
     */
    public abstract void execute();

    /**
     * 获取最新
     * @return
     */
    public abstract int getNumber();
}

ConcreteSubject 具体被观察者

public class RandomNumberGenerator extends NumberGenerator{

    private Random random = new Random();

    private int number;

    /**
     * 执行方法
     */
    @Override
    public void execute() {
        for (int i = 0; i < 500; i++) {
            number = random.nextInt(50);
            // 唤醒观察者
            notifyObservers();
        }
    }

    @Override
    public int getNumber() {
        return number;
    }
}

Observer 观察者

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

ConcreteObserver 具体的观察者

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

代码分析

  1. Observer 执行的顺序为加入LIst集合的先后顺序;
  2. 观察者模式实际上是一种发布-订阅模式,被观察者为发布的一方,观察者为订阅的一方,接收被观察者的通知;