📅  最后修改于: 2023-12-03 15:42:12.502000             🧑  作者: Mango
该问题是[GATE CS 2020计算机科学与IT工程] (https://gateoverflow.in/283427/gate-cs-2020-set-1-question-16)的问题16。
问题:假设您需要实现具有一下功能的观察者模式。一个主题可能有多个观察者,并且当主题发生变化时,所有观察者都会得到通知。此外,每个观察者可以自行选择观察的事件类型。代码如下所示:
interface EventType {
String getName();
}
interface Observer {
void notify(EventType e);
void subscribe(EventType e);
void unsubscribe(EventType e);
}
interface Subject {
void attach(Observer o);
void detach(Observer o);
void notify(EventType e);
}
您需要实现一个名为“ EventHandler”的类,该类提供以下功能:
解决方案:为了解决问题,我们需要实现EventHandler类,并使其实现Subject接口以完成必要的操作。下面是实现的代码片段:
import java.util.*;
class EventHandler implements Subject {
private final Map<String, List<Observer>> observers;
private final Set<EventType> eventTypes;
EventHandler(EventType... eventTypes) {
this.observers = new HashMap<>();
this.eventTypes = new HashSet<>();
for (EventType e : eventTypes) {
this.observers.put(e.getName(), new ArrayList<>());
this.eventTypes.add(e);
}
}
@Override
public void attach(Observer observer) {
for (EventType e : observer.getEventTypes()) {
if (eventTypes.contains(e)) {
observers.get(e.getName()).add(observer);
}
}
}
@Override
public void detach(Observer observer) {
for (EventType e : observer.getEventTypes()) {
if (eventTypes.contains(e)) {
observers.get(e.getName()).remove(observer);
}
}
}
@Override
public void notify(EventType e) {
List<Observer> observers = this.observers.get(e.getName());
if (observers != null) {
for (Observer observer : observers) {
observer.notify(e);
}
}
}
}
在此代码片段中,EventHandler实现了Subject接口,并使用Java映射(Map)将每个事件类型的观察者列表与其关联。attach和detach方法很简单,对于每个观察者,会将其添加到或从每个事件类型的观察者列表中。notify方法检查观察者列表以查找订阅给定事件类型的观察者,然后调用notify方法以通知它们。
同时,还需要实现Observer接口和EventType接口:
class MyEventType implements EventType {
private final String name;
MyEventType(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
class MyObserver implements Observer {
private final Set<EventType> eventTypes = new HashSet<>();
@Override
public void notify(EventType e) {
System.out.println("Notified of event: " + e.getName());
}
@Override
public void subscribe(EventType e) {
eventTypes.add(e);
}
@Override
public void unsubscribe(EventType e) {
eventTypes.remove(e);
}
Set<EventType> getEventTypes() {
return eventTypes;
}
}
在此代码片段中,MyEventType类实现EventType接口,并简单地将字符串与名称关联。MyObserver类实现Observer接口,并包含一个事件类型集合,表示它感兴趣的事件类型。它能够订阅和取消订阅每个事件类型,并实现了notify方法以处理通知。
最后,可以编写以下示例使用EventHandler:
public class Example {
public static void main(String[] args) {
MyEventType event1 = new MyEventType("Event 1");
MyEventType event2 = new MyEventType("Event 2");
EventHandler handler = new EventHandler(event1, event2);
MyObserver observer1 = new MyObserver();
MyObserver observer2 = new MyObserver();
observer1.subscribe(event1);
observer2.subscribe(event2);
handler.attach(observer1);
handler.attach(observer2);
handler.notify(event1);
handler.notify(event2);
observer1.unsubscribe(event1);
handler.notify(event1);
handler.detach(observer1);
handler.detach(observer2);
}
}
此代码片段设置了两个事件类型,Event 1和Event 2,并创建了EventHandler和两个观察者。观察者1订阅事件1,观察者2订阅事件2,并使用attach方法将两个观察者添加到事件处理程序中。最后,我们使用notify方法向每个订阅的观察者发送通知,并使用detach方法从事件处理程序中删除它们。