系列文章目录
- 【设计模式】之装饰器模式
- 【设计模式】之工厂模式(三种)
- 【设计模式】之工厂模式(三种)
前言
今天给大家介绍另一种设计模式--观察者模式,有了解webscoket实现原理的小伙伴应该对这个设计模式不陌生。不清楚也没关系,今天就给大家介绍一下这个设计模式。🌈
一、什么是观察者模式
观察者模式是一种常见的设计模式,用于在对象之间建立一对多的依赖关系。在该模式中,一个目标对象管理所有依赖于它的观察者对象,并在其状态改变时主动发出通知。
在观察者模式中,主要有以下几个角色:
- Subject(目标/主题/可观察者):
- 定义了被观察者需要实现的接口,通常包含添加、删除观察者以及通知所有观察者的方法。
- 用来保存注册的观察者对象,它可以是一个具体的被观察对象,也可以是一个抽象类或接口。
- 当其内部状态改变时,会通过某种方式(如调用方法)通知所有注册的观察者对象。
- Observer(观察者/监听者):
- 定义了一个更新接口,使得在得到目标的改变通知时更新自己。
- 可以是具体的观察者对象,也可以是一个抽象类或接口。
- 实现了观察者接口的对象可以在目标对象改变时收到通知。
- ConcreteSubject(具体目标/具体可观察者):
- 实现了目标接口,在内部状态改变时,会通知所有注册的观察者对象。
- 通常包含有经常发生改变的数据。
- ConcreteObserver(具体观察者/具体监听者):
- 实现了观察者接口,实现具体的更新方法,以便在得到目标的改变通知时执行具体的动作。
- 根据需要,可以更新目标的状态或做某些动作。
UMl类图
二、有哪些应用场景
最常见的就是前后端实时通信的webscoket,观察者模式在其他实际应用中也具有广泛的应用场景,比如:
- 事件处理:观察者模式常被用于事件处理机制,其中观察者对象订阅特定事件,并在事件发生时接收通知并执行相应的操作。例如,在图形用户界面(GUI)框架中,按钮的点击事件、窗口的打开和关闭事件等都可以使用观察者模式进行处理。
- 消息通知:观察者模式在消息通知系统中得到广泛应用。当发布者发布新消息时,订阅该消息的观察者将收到通知并进行相应的处理。这种模式常见于聊天应用、社交媒体平台等需要实时消息传递的场景。
- 实时数据更新:在需要实时更新数据的应用中,观察者模式可以用于将数据源与数据消费者连接起来。当数据源的数据发生变化时,观察者可以自动获取最新的数据并进行处理。
- 股票市场:股票市场应用程序可以使用观察者模式来监测股票价格变化,并将这些变化通知给投资者。
- 游戏开发:在游戏中,观察者模式可用于处理各种事件,如玩家输入、碰撞检测、角色状态变化等。当游戏角色的位置发生变化时,所有观察者(例如地图)都能收到通知,从而更新图形显示。
- 网络通信:在网络应用中,观察者模式可用于实现即时通信系统,其中用户之间的消息传递可以通过观察者模式来实现。
三、案例
我就以取快递这个案例为例,首先驿站拿到我们的快递后会给我们发送取件码,通知我们取件,然后我们接收到通知后,拿着取件码取件;这个过程中,驿站就是被观察者,我们自己就是观察者。接下来我们用代码实现这个过程。
首先,定义观察者接口或者抽象类
public abstract class Customer {
public abstract void update();
}
具体观察者
public class CustomerA extends Customer{
@Override
public void update() {
System.out.println("顾客A的快递已送达");
}
}
public class CustomerB extends Customer{
@Override
public void update() {
System.out.println("顾客B的快递已送达");
}
}
定义主题或目标接口
public interface Subject {
void registerCustomer(Customer o);
void removeCustomer(Customer o);
void notifyCustomers();
}
具体观察者
public class PostStation implements Subject{
private List<Customer> customerList ;
public PostStation(){
this.customerList = new ArrayList<>();
}
//添加顾客
@Override
public void registerCustomer(Customer o) {
customerList.add(o);
}
//删除顾客
@Override
public void removeCustomer(Customer o) {
customerList.remove(o);
}
//通知所有顾客
@Override
public void notifyCustomers() {
for (Customer customer : customerList){
customer.update();
}
}
//对外提供取快递方法
public void PostExpress(){
this.notifyCustomers();
}
}
void test1(){
//创建一个驿站
PostStation postStation = new PostStation();
Customer customerA = new CustomerA();
Customer customerB = new CustomerB();
//添加两位顾客
postStation.registerCustomer(customerA);
postStation.registerCustomer(customerB);
//通知所以顾客取快递
postStation.notifyCustomers();
}
总结
优点
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 目标与观察者之间建立了一套触发机制,使得当目标状态改变时,可以自动通知所有观察者。
- 支持广播通信,目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
- 满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,增加新的观察目标也很方便。
缺点
- 观察者对象很多时,通知的发布会花费很长时间,影响程序的效率
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化