观察者模式(Observer Pattern)

参考文档:https://www.cnblogs.com/itTeacher/archive/2012/12/03/2800129.html

定义:

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

模式组成:

  • Subject:被观察者抽象角色主题接口,即可观察者Observable,对象使用此接口注册为观察者,或者把自己从观察者中删除,每个主题可以有多个观察者。
  • Observer:观察者抽象角色所有潜在的观察者必须实现观察者接口,这个接口只有update方法,当主题改变时,它被调用。
  • ConcreteSubject:被观察者的具体实现一个具体主题实现了主题接口,除了注册和撤销之外,具体主题还实现了notifyObservers()方法,这个方法用来在主题状态改变时更新所有观察者。具体主题也可能有设置和获取状态的方法
  • ConcreteObserver:观察者的具体实现具体观察者可以是任何实现了Observer接口的类。观察者必须注册具体主题,一边接收更新。

uml类图:

优点:

  •  Subject和Observer之间是松偶合的,分别可以各自独立改变。
  •  Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知
  • 遵守大部分GRASP原则和常用设计原则,高内聚低偶合

应用场景:

  •  对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变
  •  对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
      • java.util.EventListener
      • javax.servlet.http.HttpSessionBindingListener
      • javax.servlet.http.HttpSessionAttributeListener
      • javax.faces.event.PhaseListener

举个栗子:

定义一个观察者抽象角色

interface Observer {
    public void update();
}

定义一个观察者的具体实现

class Waiter implements Observer {
    @Override
    public void update() {
        System.out.println("我是服务员 该上菜啦");
    }
}

定义一个被观察者的接口

interface Subject {
    // 增加观察者
    public void add(Observer ob);
    // 删除观察者
    public void del(Observer ob);
    // 通知所有的观察者
    public void notifyObservers();
    // 具体的操作
    public void operation();
}

定义一个被观察者的抽象类

class AbstractSubject implements Subject {

    private Vector<Observer> vector = new Vector<Observer>();

    public void add(Observer ob) {
        vector.add(ob);
    }
    public void del(Observer ob) {
        vector.remove(ob);
    }
    public void notifyObservers() {
        Enumeration<Observer> enumo = vector.elements();
        while (enumo.hasMoreElements()) {
            enumo.nextElement().update();
        }
    }
    @Override
    public void operation() {
    }
}

定义一个被观察者的具体实现

class CookSubject extends AbstractSubject {
    @Override
    public void operation() {
        System.out.println("我是厨师 菜做好啦");
        notifyObservers();
    }
}

客户端调用

public static void main(String[] args) {
        Subject cook = new CookSubject();
        cook.add(new Waiter());
        cook.add(new Waiter());
        cook.operation();
    }

输出

原文地址:https://www.cnblogs.com/amei0/p/7930972.html