目录
- 三、基于事件的软件体系结构
- 代码
- 显式调用
- 隐式调用
- 事件系统软件体系结构的概念
- 事件系统的连接机制
- 例子:图形用户界面
- 事件系统调度策略
- 1.带有分离的派遣模块的事件管理器
- 观察者模式
- 类图
- 观察者模式应用实例
- 课程作业
三、基于事件的软件体系结构
计算机中,消息是具有特定含义的数据
事件:能够激活对象功能的动作。当发生这种动作后将给所涉及对象发送一个消息,对象便可执行相应的功能
代码
基于事件的软件体系结构(Event-Driven Architecture,EDA)是一种将系统设计为通过事件进行通信和协调的体系结构。在这种体系结构中,系统的各个组件通过发布和订阅事件的方式进行交互,以实现松耦合、可扩展和可维护的系统设计。
以下是一个简单的基于事件的软件体系结构的代码示例,以说明其工作原理:
// 事件发布者(Publisher)
public class EventPublisher {
private List<EventListener> listeners = new ArrayList<>();
public void addEventListener(EventListener listener) {
listeners.add(listener);
}
public void removeEventListener(EventListener listener) {
listeners.remove(listener);
}
public void publishEvent(Event event) {
for (EventListener listener : listeners) {
listener.handleEvent(event);
}
}
}
// 事件订阅者(Subscriber)
public interface EventListener {
void handleEvent(Event event);
}
// 事件定义
public class Event {
private String data;
public Event(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
// 事件处理器(Event Handler)
public class EventHandler implements EventListener {
@Override
public void handleEvent(Event event) {
String data = event.getData();
System.out.println("Event received: " + data);
// 进行事件处理逻辑
}
}
在上述代码示例中,EventPublisher
负责发布事件,它维护了一个事件监听器列表,并提供了添加、移除和发布事件的方法。EventListener
接口定义了事件订阅者的行为,其中的handleEvent
方法用于处理接收到的事件。Event
类表示事件对象,其中包含了事件的数据。
当事件发布者调用publishEvent
方法发布事件时,所有注册的事件监听器(订阅者)都会收到该事件并调用其handleEvent
方法进行处理。在示例中,EventHandler
实现了EventListener
接口,它的handleEvent
方法打印了接收到的事件数据,并执行了相应的事件处理逻辑。
基于事件的软件体系结构的优点包括:
- 松耦合:组件之间通过事件进行通信,彼此解耦,降低了依赖性。
- 可扩展性:新的组件可以通过订阅事件来扩展系统功能,不需要修改现有组件。
- 可维护性:各个组件之间相互独立,修改一个组件不会对其他组件产生影响。
- 异步处理:事件的发布和处理是异步进行的,可以提高系统的响应性能。
总结而言,基于事件的软件体系结构通过事件的发布和订阅机制实现组件之间的通信和协调,具有松耦合、可扩展和可维护等优点。它适用于需要异步处理和松散耦合的系统设计,可以帮助构建灵活且具有良好扩展性的软件系统。
显式调用
隐式调用
隐式调用将调用者与被调用者解耦,调用者可以不知道谁是被调用者。也不知道调用后的后果如何。
事件系统软件体系结构的概念
事件系统的连接机制
连接件:事件-过程绑定
过程<事件处理器,事件的接收和处理方>向特定的事件进行注册
构件<事件源>发布事件
当某些事件被发布时,向其注册的过程被隐式调用
调用的次序是不确定的
在某些情况下,一个事件也可能触发其他事件,形成事件链。
这种连接机制成为“事件—事件绑定”。
例子:图形用户界面
事件系统调度策略
1.带有分离的派遣模块的事件管理器
事件派遣模块
功能:负责接收到来的事件并派遣它们到其他模块
派遣方式:
1.广播式:派遣模块将事件广播到所有的模块,但只有感兴趣的模块才去取事件,并触发自身的行为
2.选择广播式:派遣模块将事件送到那些已经注册了的模块中
观察者模式
类图
- Observable:被观察者接口,声明了三个应该实现的方法。在简单的情况下,2. register(obs:Observer) 方法负责将参数中的观察者注册到Subject对象,在Subject对象中保持一个具体的观察者列表,用于记载所有的观察者。unRegister(obs:Observer) 方法用于在列表中删除参数中观察者对象。Notify() 方法用于通知观察者subject状态的改变。
- Subject:具体的观察者要依赖的对象,它要实现Observable的所有方法。在Subject中的getState() 方法可以被ConcreteObserver调用,以便得到最新的状态。
- Observer:观察者接口,代表依赖对象。观察者可以有多个。
- ConcreteObserver:代表具体的观察者对象。
关于setChanged
分为两种情况
1.传统模式
在传统模式中,Observable是接口,方法是可以自己定义的,一般来说就三个方法,注册,取消注册,通知
2.Java API模式
在传统模式中,Observable是抽象类,setChanged是必须的,而且是用来设置一个 boolean 类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers() 才会通知观察者。一般来说,也是三个方法,注册,改变状态,通知
观察者模式应用实例
课程作业
当调用Observable类的notifyObserver之前,还应该同时调用什么方法?
在调用Observable类的notifyObserver
方法之前,应该先调用setChanged
方法。
setChanged
方法是Observable类的一个方法,用于设置对象的状态已经改变。它会将Observable对象的changed
字段设置为true,表示对象的状态已经发生了改变。
在观察者模式中,当被观察对象的状态发生改变时,需要先调用setChanged
方法来标记状态已经改变,然后再调用notifyObserver
方法通知所有观察者。这样做的目的是确保只有当状态发生改变时才会通知观察者,避免不必要的通知。
因此,在调用notifyObserver
方法之前,应该先调用setChanged
方法来设置对象的状态已经改变。这样可以确保观察者能够正确地接收到状态改变的通知。
1、设计类图:
2、解释:
Observable和Observer为接口类,FishbowlGUI为被观察类(实现Observable接口),ChemistryGUI、TemperatureGUI、LevelGUI为观察者类(实现Observer接口)。
FishbowlGUI有3个私有变量quality、temperature和level,分别代表鱼缸的水质、水温和水位高度,每个私有变量都有其对应的get和set方法。
三个观察者类都要实现takeAction(Observable s)方法,每个类实现该方法的方式不同:
- 当quality超过特定范围时,化学传感器ChemistryGUI排除鱼缸部分废水,补充新水;
- 当temperature低于或高于特定温度时,TemperatureGUl开启加热设备或者冷却设备调整水温;
- 当level高于或低于特定高度时,LevelGUI开启排水设备,排除部分水或者添加新鲜的水。
该方法通过参数传入一个被观察者对象,当得到通知后,将对被观察者类FishbowlGUI的某些方法进行调用,以便获取变化的状态。
1、设计类图:
2、AirportInfo类三个方法的功能:
- AddObserver(Observer obs)方法,将多个观察者添加到被观察者的observerList中,以便在通知观察者时使用;
- setChanged()和notifyObservers(),通知观察者被观察者对象的状态已经改变,同时会运行观察者对象的update()方法。执行顺序为:setChanged()先执行,notifyObservers()后执行。
3、update方法的参数:
- 第一个参数为Observable类型,代表被观察者对象;
- 第二个参数为Object类型,代表发生的事件,Object为被观察者的一种状态值,提供给update()方法,以便更新观察者。
4、具体行为:
- VoiceInfo类的update()方法完成的工作是从AirportInfo类获取语音机场信息,然后将这些信息发送给乘客;
- DisplayInfo类的update()方法负责从AirportInfo类获取文字机场信息,然后将这些信息显示在屏幕上。
5、工作原理:
- 被观察者AirportInfo有一个observerList(ArrayList类型)成员变量,用于记载动态添加的观察者。
- 对被观察者状态感兴趣的对象(观察者)VoiceInfo和DisplayInfo,应该调用被观察者的addObserver()方法将自己注册为它的一个观察者。
- 每当AiportInfo的状态发生改变时,它将调用setChanged()方法和notifyObservers()方法(通知已经注册的观察者VoiceInfo和DisplayInfo)。
- 接收到通知以后,VoiceInfo和DisplayInfo都将查询AirportInfo的状态,以便保持状态同步。根据新的状态,VoiceInfo和DisplayInfo将分别调用update()方法执行相关操作。