Java设计模式 - 程序员古德
定义“
观察者模式定义了一对多的依赖关系,让多个观察者同时监听一个主题对象,当主题状态改变时,所有观察者都会自动收到通知并更新,以新闻发布会为例,新闻机构发布消息时,所有关注的记者和订阅者都会收到通知并进行独立处理,这就是典型的观察者模式应用,该模式实现了松耦合,主题和观察者之间不需相互了解具体实现细节。
”
程序员必知!观察者模式的实战应用与案例分析 - 程序员古德
观察者模式它定义了对象间的一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,它的所有依赖者(观察者)都会自动收到通知并更新。
举个现实业务中的形象例子:想象一个新闻发布会的场景,在这个场景中,新闻机构发布了一些重要消息,而记者和订阅者(观察者)都希望尽快得到这些消息,当新闻机构发布新消息时,所有关注的记者和订阅者都会收到通知,并根据这些消息进行自己的报道或行动。
具体来说:
- 新闻机构:负责产生和发布新闻消息,当有新的消息时,它会通知所有关注的记者和订阅者。
- 记者和订阅者(观察者):他们关注新闻机构,希望在其发布新消息时得到通知,每个记者或订阅者都可以根据接收到的消息进行独立处理,比如撰写报道、更新社交媒体状态等。
在这个例子中,新闻机构和记者/订阅者之间的关系就是典型的观察者模式,新闻机构不需要知道具体有哪些记者或订阅者在关注它,它只需要在适当的时候发布消息,同样,记者和订阅者也不需要知道新闻机构是如何产生消息的,他们只需要在消息发布时得到通知并进行处理。
代码案例程序员必知!观察者模式的实战应用与案例分析 - 程序员古德
反例在未使用观察者模式的情况下,通常会采用直接调用或轮询的方式来通知依赖对象状态的改变,这种方式不仅增加了代码之间的耦合性,还可能导致效率低下和资源浪费,下面是一个未使用观察者模式的反例代码:
// 主题类,负责维护状态并通知观察者(但在这个例子中,并没有实现观察者模式)
public class Subject {
private String state;
// 假设这是唯一关注该主题的“观察者”(实际上这并不是观察者模式的实现)
private ConcreteObserver observer;
public Subject(ConcreteObserver observer) {
this.observer = observer;
}
public void setState(String state) {
this.state = state;
// 直接调用观察者的更新方法
observer.update(state);
}
public String getState() {
return state;
}
}
// 观察者接口(在这个反例中,它并没有起到应有的作用)
public interface Observer {
void update(String state);
}
// 具体的观察者类
public class ConcreteObserver implements Observer {
private String observerState;
@Override
public void update(String state) {
this.observerState = state;
System.out.println("ConcreteObserver's state updated to: " state);
}
public String getObserverState() {
return observerState;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 创建观察者
ConcreteObserver observer = new ConcreteObserver();
// 创建主题并将观察者传入(尽管这里传入了,但并没有利用观察者模式的优点)
Subject subject = new Subject(observer);
// 更改主题状态
subject.setState("new state");
// 输出观察者的状态
System.out.println("Observer's state after update: " observer.getObserverState());
// 假设需要添加另一个观察者,但由于没有使用观察者模式,这将会很困难
// 不得不修改Subject类来适应新的观察者
}
}
在这个例子中,Subject 类直接持有一个 ConcreteObserver 的引用,并在状态改变时直接调用它的 update 方法,这种方式的问题在于:
- 紧密耦合:Subject 类与 ConcreteObserver 类紧密耦合在一起,如果要添加新的观察者或者更改现有的观察者,就不得不修改 Subject 类的代码。
- 不易扩展:如果想要添加多个观察者,就不得不为每个观察者都添加一个引用,并在 setState 方法中调用它们的 update 方法。
- 违反开闭原则:对 Subject 类的任何修改都可能引入新的错误,并且违反了开闭原则。
下面是一个使用观察者模式的正例代码实现,在这个例子中,有一个Subject接口,它定义了注册、移除和通知观察者的方法,ConcreteSubject类实现了这个接口,并维护了一个观察者列表,Observer是一个接口,定义了观察者更新其状态的方法,ConcreteObserver实现了这个接口,如下代码:
// 观察者接口
public interface Observer {
void update(String state);
}
// 具体观察者类
public class ConcreteObserver implements Observer {
private String observerState;
@Override
public void update(String state) {
// 更新观察者的状态
this.observerState = state;
System.out.println("ConcreteObserver's state updated to: " state);
}
}
// 主题接口
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String state);
}
// 具体主题类
import java.util.ArrayList;
import java.util.List;
public class ConcreteSubject implements Subject {
// 维护一个观察者列表
private List<Observer> observers = new ArrayList<>();
private String subjectState;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String state) {
// 遍历观察者列表并通知每个观察者
for (Observer observer : observers) {
observer.update(state);
}
}
// 设置主题状态的方法,状态改变时通知观察者
public void setState(String state) {
this.subjectState = state;
notifyObservers(state);
}
public String getState() {
return subjectState;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 创建具体主题和观察者
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
// 注册观察者
subject.registerObserver(observer);
// 改变主题状态
subject.setState("new state");
// 取消注册观察者
subject.removeObserver(observer);
// 再次改变主题状态,此时观察者不再接收通知
subject.setState("another new state");
}
}
运行结果将会是:
ConcreteObserver's state updated to: new state
这里展示了观察者模式的核心思想:主题维护一个观察者列表,当主题状态发生变化时,所有注册的观察者都会收到通知,这种方式降低了主题和观察者之间的耦合性,使得可以独立地改变主题或观察者,而不会影响到对方,同时,它也可以动态地添加或移除观察者,从而增加了代码的灵活性和可扩展性。
核心总结程序员必知!观察者模式的实战应用与案例分析 - 程序员古德
观察者模式是一种行为设计模式,它能够在对象之间建立一种一对多的依赖关系,这样一来,当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。主要体现在,1、主题与观察者之间代码依赖度低,双方只依赖于抽象接口,而不是具体实现,易于扩展和维护,2、主题状态变化时,可以自动通知所有已注册的观察者,实现一对多的通信。在使用观察者模式时需要考虑一些注意点,1、如果观察者之间或间接地相互依赖,可能引发循环调用和系统崩溃,2、在观察者数量多或通知操作复杂时,频繁的通知可能导致性能下降,3、在多线程环境下,通知过程可能需要同步措施来避免数据不一致问题。
关注我,每天学习互联网编程技术 - 程序员古德