JavaでのMediatorデザインパターン
メディエーターデザインパターンは、行動デザインパターンの一つで、オブジェクトの振る舞いに関わるものです。メディエーターデザインパターンは、システム内の異なるオブジェクト間で集中したコミュニケーション手段を提供するために使用されます。
メディエーターの設計パターン
GoFによれば、メディエーターパターンの意図は次のようです。
異なるオブジェクトセットが相互にやり取りし、通信する方法をカプセル化することで、ゆるやかな結合を実現します。それぞれのオブジェクトセットのアクションが互いに独立して変化することができます。
メディエータデザインパターンは、複数のオブジェクトが相互にやり取りするエンタープライズアプリケーションで非常に役立ちます。オブジェクトが直接やり取りすると、システムのコンポーネントは互いに強く結合され、保守性コストが高く、拡張が難しくなります。メディエータパターンは、オブジェクト間の通信のための中間者を提供し、オブジェクト間の緩やかな結合を実現することに焦点を当てています。航空管制官は、異なる飛行機間の通信のための中間者として機能するメディエータパターンの素晴らしい例です。メディエータはオブジェクト間のルーターとして機能し、通信手段を提供するために独自のロジックを持つことができます。お互いに通信するシステムオブジェクトは「同僚」と呼ばれます。通常、通信の契約を提供するインターフェースや抽象クラスがあり、その後にメディエータの具体的な実装があります。私たちの例では、グループチャットが可能なチャットアプリケーションを実装してみましょう。各ユーザーは名前で識別され、メッセージを送受信することができます。ユーザーが送信したメッセージは、グループ内のすべての他のユーザーに受信されるべきです。
メディエーターパターンのインタフェース
最初に、具体的な仲介者の契約を定義するMediatorインターフェースを作成します。ChatMediator.java
package com.scdev.design.mediator;
public interface ChatMediator {
public void sendMessage(String msg, User user);
void addUser(User user);
}
仲介者パターンのColleagueインターフェース
ユーザーはメッセージを送受信することができるので、ユーザーインターフェースまたは抽象クラスを使用できます。私は以下のように、Userを抽象クラスとして作成しています。User.java
package com.scdev.design.mediator;
public abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator med, String name){
this.mediator=med;
this.name=name;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
ユーザーは、異なるユーザー間での通信には必要なので、仲介者オブジェクトへの参照を持っていることに注意してください。
具体的な調停者
今から具体的なメディエータクラスを作成します。このクラスには、グループ内のユーザーのリストが含まれており、ユーザー間の通信に関するロジックを提供します。ChatMediatorImpl.java
package com.scdev.design.mediator;
import java.util.ArrayList;
import java.util.List;
public class ChatMediatorImpl implements ChatMediator {
private List<User> users;
public ChatMediatorImpl(){
this.users=new ArrayList<>();
}
@Override
public void addUser(User user){
this.users.add(user);
}
@Override
public void sendMessage(String msg, User user) {
for(User u : this.users){
//message should not be received by the user sending it
if(u != user){
u.receive(msg);
}
}
}
}
メディエータデザインパターンの具体的な同僚 (Medieeta dezain patān no gutaiteki na dōryō)
今では、クライアントシステムで使用するために具体的なUserクラスを作成することができます。UserImpl.java
package com.scdev.design.mediator;
public class UserImpl extends User {
public UserImpl(ChatMediator med, String name) {
super(med, name);
}
@Override
public void send(String msg){
System.out.println(this.name+": Sending Message="+msg);
mediator.sendMessage(msg, this);
}
@Override
public void receive(String msg) {
System.out.println(this.name+": Received Message:"+msg);
}
}
send()メソッドは、ユーザーにメッセージを送るためにメディエータを使用していることに注意してください。そして、どのようにメディエータによって処理されるかについては全く知りません。
メディエーターパターンの例のクライアントプログラムのコード
簡単なプログラムで、このチャットアプリケーションをテストしましょう。仲介者を作成し、グループにユーザーを追加し、そのうちの一人がメッセージを送信します。ChatClient.java
package com.scdev.design.mediator;
public class ChatClient {
public static void main(String[] args) {
ChatMediator mediator = new ChatMediatorImpl();
User user1 = new UserImpl(mediator, "Pankaj");
User user2 = new UserImpl(mediator, "Lisa");
User user3 = new UserImpl(mediator, "Saurabh");
User user4 = new UserImpl(mediator, "David");
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
mediator.addUser(user4);
user1.send("Hi All");
}
}
クライアントプログラムは非常にシンプルであり、メッセージがどのように処理され、ユーザーが中間者に取得されるかどうかを全く知りません。中間者パターンの例プログラムの出力は次のとおりです。
Pankaj: Sending Message=Hi All
Lisa: Received Message:Hi All
Saurabh: Received Message:Hi All
David: Received Message:Hi All
メディエーターパターンのクラス図
JDKにおけるMediatorパターンの例。
- java.util.Timer class scheduleXXX() methods
- Java Concurrency Executor execute() method.
- java.lang.reflect.Method invoke() method.
メディエーターデザインパターンの重要なポイント
- Mediator pattern is useful when the communication logic between objects is complex, we can have a central point of communication that takes care of communication logic.
- Java Message Service (JMS) uses Mediator pattern along with Observer pattern to allow applications to subscribe and publish data to other applications.
- We should not use mediator pattern just to achieve lose-coupling because if the number of mediators will grow, then it will become hard to maintain them.
これで、仲介者デザインパターンとそのJavaでの実装は終わりです。