发送状态变化通知-Observer模式

85 阅读2分钟

1、引入

Observer,译为观察者,观测者。

而在Observer模式中,当被观测对象发生改变时,观测者会得知改变并且对其进行相关反应,这种改变的得知是由被观测对象反映给观测者的。

2、示例

实现以下功能,被观测者会随机产生数字,两个观测者能够分别以数字和图形的方式在得知后展示随机数字。

2.1、被观测者-随机数字生产类

2.1.1、数字生产抽象父类

public abstract class NumberGenerator {
    private ArrayList<Observer> observers=new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void deleteObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers() {
        for (Observer o : observers) {
            o.update(this);
        }
    }

    public abstract int getNumber();

    public abstract void execute();
}

2.1.2、随机数字生产子类

public class RandomNumberGenerator extends NumberGenerator{
    private Random random=new Random();
    int number;
    @Override
    public int getNumber() {
        return number;
    }

    @Override
    public void execute() {
        for (int i = 0; i < 20; i++) {
            number=random.nextInt(50);
            notifyObservers();
        }
    }
}

2.2、观测者

2.2.1、观察者统一接口

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

2.2.2、数字观察者

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

2.2.3、图形观测者

public class GraphObserver implements Observer{
    @Override
    public void update(NumberGenerator generator) {
        System.out.println("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) {
            e.printStackTrace();
        }
    }
}

2.3、测试

public class Main {
    public static void main(String[] args) {
        NumberGenerator generator = new RandomNumberGenerator();
        //添加观测者
        generator.addObserver(new DigitObserver());
        generator.addObserver(new GraphObserver());
        //随机生成数字
        generator.execute();
    }
}

运行结果(部分):

image.png

3、tips

  • 观察?通知?:从上例来看,与其说是观测,不如说是被观测者主动通知观测者发送了变化比较合适。
  • 组件化:RandomNumberGenerator并不知道随在观察它,但是所有观测者都实现了Observer接口,只需要通过notifyObservers()方法来调用观测者们的update()方法;同样的,Observer们不知道自己在检测谁,但是生产数字的类都继承了NumberGenerator抽象类,调用update()时只需要调用抽象类的getNumber()方法即可。这样做的好处是在实际生产中可以灵活拼接被观测者和观测者,实现了组件化。