23天学习23种设计模式——观察者模式
前言
在日常生活中,比如我们订阅报纸或者订牛奶。或者在网络上,RSS方式订阅别人的博客,微博follow某人,以及现在很火的即刻app。都是采取的订阅的模式。当我们需要报纸,牛奶,以及查看别人博客/微博,或是某种主题的消息,我们只需采取订阅的方式在发布方注册一下即可。当我们不需要的时候,只要取消订阅就可以了。在软件开发中,同样有利用这种原理的设计模式——观察者模式。
是什么
观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。
观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
下图就是观察者模式结构图:
有如下角色:
- Subject: 目标
- ConcreteSubject:具体目标
- Observer: 观察者
- ConcreteObserver:具体观察者
为什么
还是以日常生活举例,当我们想要查看某人的博客是否有更新的时候。我们可以直接在浏览器中输入博客地址进行查看。但是这样一种方式,往往效率不高。有可能几天内都没有更新。但是如果我们采用RSS方式订阅的话,我们能在第一事件收到对方博客更新的消息。其他时候,我们可以处理别的事物,而不用主动查看是否有更新。同理,在软件开发中。一些对象如果对对象A的状态的变化感兴趣,采用观察者模式来订阅它的状态更新,这样就不用持有对象A的引用了。降低了对象之间的耦合。
怎么做
首先是主题Subject类的实现,它使用集合持有订阅者,订阅者通过attach
方法订阅主题,detach
方法取消订阅,当主题的state发生变化时,通过notifyObservers
通知订阅者,主题状态有更新:
/**
* 主题,被观察对象
*/
public class Subject {
private List<Observer> observers = new ArrayList<>();//订阅者链表
private int state;//主题状态
public void attach(Observer observer){
if(observer!=null){
observers.add(observer);
}
}
public void detach(Observer observer){
observers.remove(observer);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
public void notifyObservers(){
for(Observer observer:observers){
observer.update(this);
}
}
}
然后时订阅者类的实现,一般是一个抽象类或者接口:
/**
* 观察者
*/
public interface Observer {
void update(Subject subject);
}
接着时具体观察者类的实现,在update
方法中对主题状态改变进行具体操作:
public class BinaryObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Binary String:"+Integer.toBinaryString(subject.getState()));
}
}
public class HexObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Hex String:"+Integer.toHexString(subject.getState()));
}
}
public class OctalObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Octal String:"+Integer.toOctalString(subject.getState()));
}
}
最后,我们写个Client
类看看具体应用:
public class Client {
public static void main(String[] args) {
Subject subject = new Subject();
HexObserver hexObserver = new HexObserver();
OctalObserver octalObserver = new OctalObserver();
BinaryObserver binaryObserver = new BinaryObserver();
//观察者订阅主题
subject.attach(hexObserver);
subject.attach(octalObserver);
subject.attach(binaryObserver);
System.out.println("Set state:15");
subject.setState(15);//设置状态
System.out.println("-----------------");
//取消订阅主题
subject.detach(octalObserver);
System.out.println("Set state:24");
subject.setState(24);//改变状态
}
}
运行结果:
运行结果