《大话设计模式》读书笔记 - 观察者模式

观察者模式的定义?


观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们可以自动的更新自己

例如:微信公众号是主题,用户是观察者,用户可以订阅公众号也可以取消订阅,当公众号有新文章时就会通知所有已订阅的用户。

观察者模式使用场景


- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

观察者模式类图


《大话设计模式》读书笔记 - 观察者模式_第1张图片

  • 主题接口:也就是一个抽象主题,抽象主题提供一个接口,可以增加和删除观察者角色,并通知所有观察者更新数据。
  • 观察者接口:主要是提供一个update操作,在得到主题通知时会执行更新操作。
  • 具体主题:具体主题实现了抽象主题的接口,同时可以定义一个ArrayList用来存放所有的观察者,在Notify函数中向所有登记过的观察者发出通知,即对每一个观察者执行update操作。
  • 具体观察者:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

实战学习


**定义一个主题接口,主要有三个方法**
public interface Subject {

    /**
     * 添加集合中不存在的观察者对象
     *
     * @param observer
     */
    void addTach(Observer observer);

    /**
     * 从集合中移除观察者对象
     *
     * @param observer
     */
    void removeTach(Observer observer);

    /**
     * 通知
     */
    void notifyTach();
}

创建一个微信主题实现类

public class WechatSubject implements Subject {

    private List observers = new ArrayList();

    private String action;

    /**
     * 添加集合中不存在的观察者对象
     * @param observer
     */
    public void addTach(Observer observer) {
        if(! observers.contains(observer)) {
            observers.add(observer);
        }
    }

    /**
     * 从集合中移除观察者对象
     * @param observer
     */
    public void removeTach(Observer observer) {
        if(observers.contains(observer)) {
            observers.remove(observer);
        }

    }

    public void notifyTach() {

        for (Observer observer : observers) {
            observer.update();
        }
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }
}

观察者抽象类

public abstract class Observer{

    public abstract void update();
}

具体观察者用户继承抽象类

public class PeopleObserver extends Observer{

    private String name;

    private WechatSubject subject;

    public PeopleObserver(String name, WechatSubject subject) {
        this.name = name;
        this.subject = subject;
    }

    @Override
    public void update() {
        getMsg();
    }

    public void getMsg(){
        String msg = "%s 收到Wechat推送消息:%s";
        System.out.println(String.format(msg,name,subject.getAction()));
    }
}

主方法

public class Main {

    public static void main(String[] args) {
        //主题
        WechatSubject subject = new WechatSubject();
        //观察者
        PeopleObserver people1 = new PeopleObserver("张三",subject);
        PeopleObserver people2 = new PeopleObserver("李四",subject);
        PeopleObserver people3 = new PeopleObserver("王五",subject);

        //添加订阅
        subject.addTach(people1);
        subject.addTach(people2);
        subject.addTach(people3);
        //取消订阅
        subject.removeTach(people3);

        subject.setAction("吃鸡战场上线---");
        subject.notifyTach();

    }
}

执行结果:
《大话设计模式》读书笔记 - 观察者模式_第2张图片

JDK自带观察者模式


subject -> java.util.Observable(类)

void addObserver(Observer o) 
          如果观察者与集合中已有的观察者不同,则向对象的观察者集中添加此观察者。 
protected  void clearChanged() 
          指示对象不再改变,或者它已对其所有的观察者通知了最近的改变,所以 hasChanged 方法将返回 false。 
int countObservers() 
          返回 Observable 对象的观察者数目。 
void deleteObserver(Observer o) 
          从对象的观察者集合中删除某个观察者。 
void deleteObservers() 
          清除观察者列表,使此对象不再有任何观察者。 
boolean hasChanged() 
          测试对象是否改变。 
void notifyObservers() 
          如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。 
void notifyObservers(Object arg) 
          如果 hasChanged 方法指示对象已改变,则通知其所有观察者,并调用 clearChanged 方法来指示此对象不再改变。 
protected  void setChanged() 
          标记此 Observable 对象为已改变的对象;现在 hasChanged 方法将返回 true。

observer -> java.util.Observer(接口)

void update(Observable o, Object arg) 
          只要改变了 observable 对象就调用此方法。

使用jdk自带的观察者模式的缺点:

  • Observable是一个类,而不是一个接口,导致Observable类的扩展性不高,不如自己实现的观察者模式灵活

  • Observable将某些方法保护了起来(setChanged()和clearChanged()为protected),这意味着除非继承自Observable,否则将有关键的方法不能调用。导致无法通过组合的方式使其它类获得Observable类的功能

你可能感兴趣的:(Java)