Javaにおけるイベントアグリゲータパターン:大規模アプリケーションにおけるイベント管理の一元化
別名
- イベントチャネル
- イベントセントラル
- メッセージハブ
イベントアグリゲータデザインパターンの目的
イベントアグリゲータは、システム内のイベントを処理するために使用されるデザインパターンです。イベント処理ロジックを一元化することで、管理と保守が容易になります。イベントアグリゲータデザインパターンの目的は、イベント生成とイベント処理をデカップリングすることです。このデザインパターンは、複数のソースからイベントを収集し、適切なハンドラにルーティングします。
実例を用いたイベントアグリゲータパターンの詳細な説明
現実世界の例
イベントアグリゲータパターンは、車輪のハブによく例えられます。このアナロジーでは、イベントアグリゲータがハブであり、スポークがイベントソースです。ハブはすべてのスポークからイベントを収集し、適切なハンドラに配布します。
簡単に言うと
イベントアグリゲータは、複数のイベントソースが各ハンドラと直接通信するのではなく、中心的なポイントを通してイベントハンドラと通信できるようにするデザインパターンです。
Javaにおけるイベントアグリゲータパターンのプログラミング例
イベントアグリゲータを使用して複数のイベントを処理する次の例を考えてみましょう。
ジョフリー王は鉄の玉座に座り、ウェスタロスの七王国を治めています。彼は重要な情報のほとんどを、第二の指揮官である国王の手から受け取ります。国王の手自身にも多くの側近がおり、王国で発生するイベントに関する関連情報を彼に伝えています。
プログラミング例では、イベントアグリゲータパターンの実装を示します。オブジェクトの中にはイベントリスナのものもあれば、イベントエミッタのものもあり、イベントアグリゲータは両方を行います。
public interface EventObserver {
void onEvent(Event e);
}
public abstract class EventEmitter {
private final Map<Event, List<EventObserver>> observerLists;
public EventEmitter() {
observerLists = new HashMap<>();
}
public final void registerObserver(EventObserver obs, Event e) {
// implementation omitted
}
protected void notifyObservers(Event e) {
// implementation omitted
}
}
KingJoffrey
はKingsHand
からのイベントをリッスンしています。
@Slf4j
public class KingJoffrey implements EventObserver {
@Override
public void onEvent(Event e) {
LOGGER.info("Received event from the King's Hand: {}", e.toString());
}
}
KingsHand
は彼の部下であるLordBaelish
、LordVarys
、Scout
からのイベントをリッスンしています。彼らが彼に伝えることは何でも、彼はKingJoffrey
に伝えます。
public class KingsHand extends EventEmitter implements EventObserver {
public KingsHand() {
}
public KingsHand(EventObserver obs, Event e) {
super(obs, e);
}
@Override
public void onEvent(Event e) {
notifyObservers(e);
}
}
例えば、LordVarys
は毎週日曜日裏切り者を見つけ、KingsHand
に通知します。
@Slf4j
public class LordVarys extends EventEmitter implements EventObserver {
@Override
public void timePasses(Weekday day) {
if (day == Weekday.SATURDAY) {
notifyObservers(Event.TRAITOR_DETECTED);
}
}
}
次のスニペットは、オブジェクトがどのように構築され、接続されているかを示しています。
public static void main(String[] args) {
var kingJoffrey = new KingJoffrey();
var kingsHand = new KingsHand();
kingsHand.registerObserver(kingJoffrey, Event.TRAITOR_DETECTED);
kingsHand.registerObserver(kingJoffrey, Event.STARK_SIGHTED);
kingsHand.registerObserver(kingJoffrey, Event.WARSHIPS_APPROACHING);
kingsHand.registerObserver(kingJoffrey, Event.WHITE_WALKERS_SIGHTED);
var varys = new LordVarys();
varys.registerObserver(kingsHand, Event.TRAITOR_DETECTED);
varys.registerObserver(kingsHand, Event.WHITE_WALKERS_SIGHTED);
var scout = new Scout();
scout.registerObserver(kingsHand, Event.WARSHIPS_APPROACHING);
scout.registerObserver(varys, Event.WHITE_WALKERS_SIGHTED);
var baelish = new LordBaelish(kingsHand, Event.STARK_SIGHTED);
var emitters = List.of(
kingsHand,
baelish,
varys,
scout
);
Arrays.stream(Weekday.values())
.<Consumer<? super EventEmitter>>map(day -> emitter -> emitter.timePasses(day))
.forEachOrdered(emitters::forEach);
}
例を実行した後のコンソール出力。
21:37:38.737 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Warships approaching
21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: White walkers sighted
21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Stark sighted
21:37:38.739 [main] INFO com.iluwatar.event.aggregator.KingJoffrey -- Received event from the King's Hand: Traitor detected
実例を用いたイベントアグリゲータパターンの詳細な説明

Javaでイベントアグリゲータパターンを使用する場面
イベントアグリゲータパターンを使用する場面
- 複数のイベントソースとハンドラがある場合。
- イベントの生成と処理のロジックをデカップリングしたい場合。
- 一元化されたイベント管理システムが必要な場合。
Javaにおけるイベントアグリゲータパターンの現実世界の応用例
- 様々なサブシステムによって生成されたイベントを処理するためのセントラルポイントをシステムが必要とするエンタープライズアプリケーションの統合。
- インターフェースの一部のユーザーアクションが、コンポーネント間の緊密な結合なしに、他の部分に影響を与える必要がある複雑なGUIアプリケーション。
イベントアグリゲータパターンのメリットとデメリット
メリット
- デカップリング:イベント処理を一元化することで、イベントアグリゲータはコンポーネント間の直接的な相互作用を最小限に抑え、よりモジュール化され、管理しやすいシステムを実現します。
- 柔軟性とスケーラビリティの向上:セントラルアグリゲータがすべてのルーティングを処理するため、新しいパブリッシャやサブスクライバを追加する作業が少なくなります。
- コンポーネントインターフェースの簡素化:コンポーネントは、他のコンポーネントではなく、イベントアグリゲータだけを知っていればよくなります。
- イベント管理の一元化:システムの保守が容易になります。
デメリット
- アグリゲータの複雑さ:適切に設計されていない場合、イベントアグリゲータ自体が複雑で保守性の高いコンポーネントになる可能性があります。
- 潜在的なパフォーマンスボトルネック:適切にスケールされない場合、セントラルイベント処理メカニズムがシステムのボトルネックになる可能性があります。
関連するJavaデザインパターン
- メディエータ:コンポーネント間の直接通信を抽象化する点でメディエータに似ていますが、イベントメッセージに特化しています。
- オブザーバ:イベントアグリゲータパターンは、アグリゲータがイベントを観察し、サブスクライバに通知するオブザーバパターンを使用して実装されることがよくあります。
- パブリッシュ/サブスクライブ:イベントアグリゲータは、アグリゲータがブローカーとして機能するパブリッシュ/サブスクライブパターンの特別なケースと見なすことができます。