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

观察者模式是一种一对多的关系,当目标对象状态发生改变时,它会通知观察者。

1、定义

定义对象间一种一对多的关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并更新自己。

2、使用场景

  1. 当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化。
  2. 改变一个对象的时候,需要同时连带改变其他对象,并且不知道有多少对象需要连带改变。
  3. 当一个对象需要通知其他对象,但是又洗完这个对象和被通知的对象时松耦合的。

3、UML图

这里写图片描述

4、示例代码

/**
 * 观察者接口
 */
public interface Observer {

    public void update(Subject subject);
}

public class ConcreteObservers implements Observer {

    @Override
    public void update(Subject subject) {
        String state = ((ConcreteSubject) subject).getSubjectState();
        System.out.println("被观察者状态:" + state);
    }
}

public class Subject {

    private List<Observer> observers = new ArrayList<Observer>();

    /**
     * 注册观察者对象
     * 
     * @param observer
     */
    public void attach(Observer observer) {
        observers.add(observer);
    }

    /**
     * 删除观察者对象
     * 
     * @param observer
     */
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    /**
     * 通知所有观察者对象
     */
    public void notifyObservers() {
        for(Observer o : observers) {
            o.update(this);
        }
    }
}

public class ConcreteSubject extends Subject {

    //示意,目标对象状态
    private String subjectstate;

    public String getSubjectState() {
        return subjectstate;
    }

    public void setSubjectState(String state) {
        this.subjectstate = state;
        this.notifyObservers();
    }
}

5、推模型和拉模型

  • 推模型:目标对象主动向观察者推送目标对象的详细信息。推送的通常是目标对象的全部或部分数据。
public interface Observer {
    //如果把状态信息直接传给观察者,就是推模型了
    public void update(String subjectState);
}
  • 拉模型:目标对象通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到目标对象中获取。
public interface Observer {
    //具体改变的信息需要观察者自己从 subject 对象中获取
    public void update(Subject subject);
}

6、Java中的观察者模式

大家都知道 Java 中已经有观察者模式的部分实现了。就是实现 Observable 和 Observer 接口。示例如下:
被观察者

import java.util.Observable;

public class ConcreteSubject extends Observable {

    //示意,目标对象状态
    private String subjectstate;

    public void setSubjectState(String state) {
        this.subjectstate = state;
        //标识状态或内容发生改变
        setChanged();
        this.notifyObservers(state);
    }
}

观察者

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

public class ConcreteObservers implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("被观察者状态:" + arg);
    }
}

需要注意的地方:

  • 具体目标对象里面不需要再维护观察者的注册信息了,Observable 类已经帮忙实现好了。
  • 触发通知时,要先调用 setChanged() 方法,这是为了帮助实现更精细地触发控制而提供的功能。
  • update 方法能同时支持推模型和拉模型。

猜你喜欢

转载自blog.csdn.net/iluojie/article/details/80381049