📜  门| GATE CS 2020 |问题16(1)

📅  最后修改于: 2023-12-03 15:42:12.502000             🧑  作者: Mango

门 | GATE CS 2020 | 问题16

该问题是[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”的类,该类提供以下功能:

  1. 请编写一个构造函数,该构造函数具有任意数量的参数(事件类型)。内部它应该创建一个空观察者列表。
  2. 请编写一个名为“ attach”的方法,它将观察者添加到事件类型的观察者列表中。
  3. 请编写一个名为“ detach”的方法,它将观察者从事件类型的观察者列表中删除。
  4. 请编写一个名为“ notify”的方法,它会知会所有订阅给定事件类型的观察者。

解决方案:为了解决问题,我们需要实现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方法从事件处理程序中删除它们。