今天,我们开始学习行为型设计模式中的一种:观察者模式。
为什么结构型设计模式还没有学习完就开始学习行为型设计模式了呐?
因为我想先学习一下相对来说比较常用的设计模式,结构型设计模式剩下的几种:门面模式、组合模式、享元模式相对来说没那么常用,于是先跳过这几种设计模式,最后再来学习这些不太常用的。
行为型设计模式主要解决的就是”类与对象之间的交互“问题。
介绍
观察者模式 (Observer Design Pattern)也被称为发布订阅模式 (Publish-Subscribe Design Pattern)。
官方定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在观察者模式中通常包含如下几个角色:
- Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
- ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
- Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法collect(),因此又称为抽象观察者。
- ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。
一般情况下,被依赖的对象叫做被观察者,依赖的对象叫做观察者。直接看上面的概念可能会有些头疼,下面我们就看具体的代码实现,相信会帮助你理解。
原理与实现
抽象目标(Subject)
public interface Subject {
// 注册观察者
void registerObserver(Observer observer);
// 移除观察者
void removeObserver(Observer observer);
// 通知观察者
void notifyObservers(String message);
}
抽象观察者(Observer)
public interface Observer {
// 对观察目标的改变做出的响应
void update(String message);
}
具体目标(ConcreteSubject)
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
具体观察者(ConcreteObserverOne、ConcreteObserverTwo)
public class ConcreteObserverOne implements Observer {
@Override
public void update(String message) {
// 获取消息通知,执行自己的逻辑
System.out.println("观察者One被通知到:" + message);
}
}
public class ConcreteObserverTwo implements Observer {
@Override
public void update(String message) {
// 获取消息通知,执行自己的逻辑
System.out.println("观察者Two被通知到:" + message);
}
}
测试(Test)
public class Test {
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
concreteSubject.registerObserver(new ConcreteObserverOne());
concreteSubject.registerObserver(new ConcreteObserverTwo());
concreteSubject.notifyObservers("Java天下第一!");
}
}
结果:
以上代码就算是观察者模式的“模板代码”了,可以反映出代替的设计思路。在真实的开发场景中,不必拘泥于照搬上面的模板代码,还是根据业务场景来做出相应的调整,不过设计思路都是差不多的。
应用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如,邮件订阅、RSS Feeds,本质上都是观察者模式。
总结
实际上,设计模式要干的事情就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦,具体到观察者模式,它是将观察者和被观察者代码解耦。