设计模式-观察者模式

386 阅读3分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

观察者模式是指对象之间一对多的依赖关系,每当那个特定对象改变状态时,所有依赖于它的对象都会得到通知并被自动更新

通俗地来说,观察者模式实际上与报纸的订阅模式相同。报纸主要有两个角色:出版者和订阅者,出版者负责出版报纸,订阅者向出版者订阅报纸。当订阅者订阅报纸以后,出版者每次出版报纸,都会通知并推送给订阅者。

在观察者模式中,出版者称为被观察者,订阅者称为观察者。

模式结构

img

如图所示,观察者模式主要由两种角色组成:被观察者(Subject)和观察者(Observer)组成。

  • 被观察者(Subject) :以接口的形式存在,需要被实际的被观察者(Concrete Subject)实现,维护了一个观察者列表,并有attach(),detach(),notify()三种方法。其中attach()detach()分别负责添加和删除观察者。notify()负责调用观察者的update()方法进行通知和状态的更新。
  • 观察者(Observer) :以接口的形式存在,需要被实际的观察者(Concrete Observer)实现,有update()一种方法,负责提供给被观察者调用来进行通知和状态的更新。

推模型和拉模型

观察者模式根据数据推送的方式,可以分为推模型拉模型

  • 推模型:被观察者的数据更新后,向观察者通知并主动推送数据,不管被观察者需不需要。
  • 拉模型:被观察者的数据更新后,向观察者通知,但并不主动推送数据。当观察者需要数据时,则可以主动从被观察者中拉数据。

推模型和拉模型,更多的是语义和逻辑上的区别,在代码实现的过程中,完全可以写成同时支持两种模型的通用参数形式,具体可见Java.util包下的Observer接口和Observable类。

具体实现

以报纸的订阅场景为例,有一个被观察者:报社,两个观察者:个人、企业。具体实现如下:

类图:

被观察者:

/**
* 被观察者的接口
*/
public interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObserver();
}
​
/**
* 被观察者实现类:报社
*/
public class Newspaper implements Subject {
    private List<Observer> observerList;
    private String newspaperContent;
​
    public Newspaper(){
        observerList = new ArrayList<Observer>();
    }
​
    @Override
    public void attach(Observer observer) {
        observerList.add(observer);
    }
​
    @Override
    public void detach(Observer observer) {
        observerList.remove(observer);
    }
​
    @Override
    public void notifyObserver() {
        for (int i = 0; i < observerList.size(); i++) {
            observerList.get(i).update(newspaperContent);
        }
    }
​
    public String getNewspaperContent() {
        return newspaperContent;
    }
​
    public void setNewspaperContent(String newspaperContent) {
        this.newspaperContent = newspaperContent;
    }
}

观察者:

/**
* 观察者接口
*/
public interface Observer {
    void update(String newspaperContent);
}
​
/**
* 观察者实现类:人
 */
public class People implements Observer{
    private String name;
    private String newspaperContent;
​
    public People(String name) {
        this.name = name;
    }
​
    @Override
    public void update(String newspaperContent) {
        this.newspaperContent = newspaperContent;
        System.out.println("我是"+this.name+",我收到了报纸,报纸内容是:"+this.newspaperContent);
    }
}
​
/**
* 观察者实现类:企业
 */
public class Company implements Observer{
    private String name;
    private String newspaperContent;
​
    public Company(String name) {
        this.name = name;
    }
​
    @Override
    public void update(String newspaperContent) {
        this.newspaperContent = newspaperContent;
        System.out.println(this.name+"收到了报纸,报纸内容是:"+this.newspaperContent);
    }
​
}