技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

javaでのMediatorパターン

Mediatorパターンはデザインパターンの一つで、複雑に絡み合ったオブジェクト間の関係をMediator(調停者)が整理するパターンです。
例えば、10個のオブジェクト間で連携を取る必要がある場合、オブジェクト同士で直接連携を取ると、「自分以外の9個のオブジェクトに対する調整処理 × 10個のオブジェクト」で90通りの調整処理が必要になってしまいます。
しかし、調停者のオブジェクトを新たに作成し、その調停者を通して調整することにすれば、「調停者に対する調整処理 ×10個のオブジェクト」で10通りの調整処理で済みます。
 
ある資源に対して作用するプロセスやボタン等が多い場合に効果を発揮するパターンです。
 
以下、サンプルコードです。
誰かが実施すれば良い作業に対して、複数の作業者が作業しようとする例です。
 
【サンプルコード】
・Mediator.java
// 作業を管理する調停者の抽象クラス
public abstract class Mediator {

    // 作業名
    private String name;

    public Mediator(String name) {
        this.name = name;
    }

    public String getName(){
        return name;
    }

    // 作業実施を報告するメソッド
    public abstract void setColleague(Colleague colleague);

    // 作業実施状況を管理するメソッド
    public abstract boolean isDoneConsultation();
}
 
・ConcreteMediatorA.java
// 作業を管理する丁寧な調停者の具象クラス
public class ConcreteMediatorA extends Mediator {

    // 作業を完了させた同僚
    private Colleague doneColleague = null;

    public ConcreteMediatorA(String name) {
        super(name);
    }

    public void setColleague(Colleague colleague) {
        if (doneColleague == null) {
            doneColleague = colleague;
            System.out.println
                (this.getName() + "の実施ありがとう、" +
                 colleague.getName() + "さん。");
        // 管理することでここに飛ばないようにすることができる
        } else {
            System.out.println
                (colleague.getName() + "さん、残念ですが" +
                 this.getName() + "はもう実施済みなんですよね…。");
        }
    }

    public boolean isDoneConsultation() {
        if (doneColleague == null) {
            System.out.println
                ("まだ" + this.getName() +"は実施されていません。");
            return false;
        } else {
            System.out.println
                (this.getName() + "はもう" +
                 doneColleague.getName() + "さんが実施しました。");
            return true;
        }
    }

}
 
・ConcreteMediatorB.java
// 作業を管理するフランクな調停者の具象クラス
public class ConcreteMediatorB extends Mediator {

    // 作業を完了させた同僚
    private Colleague doneColleague = null;

    public ConcreteMediatorB(String name) {
        super(name);
    }

    public void setColleague(Colleague colleague) {
        if (doneColleague == null) {
            doneColleague = colleague;
            System.out.println
                (this.getName() + "サンキュー、" +
                 colleague.getName() + "さん。");
        // 管理することでここに飛ばないようにすることができる
        } else {
            System.out.println
                (colleague.getName() + "さん、" +
                 this.getName() + "はもうやっちゃったんだよね…。");
        }
    }

    public boolean isDoneConsultation() {
        if (doneColleague == null) {
            System.out.println
                (this.getName() +"はまだやってないぜ。");
            return false;
        } else {
            System.out.println
                (this.getName() + "はもう" +
                 doneColleague.getName() + "さんがやったよ。");
            return true;
        }
    }

}
 
・Colleague.java
// 作業を実施する同僚の抽象クラス
public abstract class Colleague {

    private String name;

    // 行う作業の調停者
    protected Mediator mediator;

    public Colleague(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public void setMediator(Mediator mediator){
        this.mediator = mediator;
    }

    // 作業の実施状況のアドバイスを求める
    public abstract boolean needsAdvice();

    // 作業を実施する
    public abstract void run();
}
 
・ConcreteColleagueA.java
// 作業を実施する丁寧な同僚の具象クラス
public class ConcreteColleagueA extends Colleague {

    public ConcreteColleagueA(String name) {
        super(name);
    }

    public boolean needsAdvice() {
        System.out.println(mediator.getName() + "は終わりましたか?");
        return mediator.isDoneConsultation();
    }

    public void run() {
        System.out.println(mediator.getName() + "を実施しました。");
        mediator.setColleague(this);
    }

}
 
・ConcreteColleagueB.java
// 作業を実施するフランクな同僚の具象クラス
public class ConcreteColleagueB extends Colleague {

    public ConcreteColleagueB(String name) {
        super(name);
    }

    public boolean needsAdvice() {
        System.out.println(mediator.getName() + "終わった?");
        return mediator.isDoneConsultation();
    }

    public void run() {
        System.out.println(mediator.getName() + "やったよ。");
        mediator.setColleague(this);
    }

}
 
・MediatorMain.java
// メインクラス
public class MediatorMain {

    public static void main(String[] args){

        // オブジェクトの生成
        Mediator mediatorA = new ConcreteMediatorA("作業A");
        Mediator mediatorB = new ConcreteMediatorB("作業B");
        Colleague colleagueA = new ConcreteColleagueA("作業者A");
        Colleague colleagueB1 = new ConcreteColleagueB("作業者B1");
        Colleague colleagueB2 = new ConcreteColleagueB("作業者B2");

        // 作業Aに着手
        // A→B1→B2の順番に作業実施
        // 作業者同士で連携を取ると、runメソッドが2×3=6つ必要になってしまう
        run(colleagueA, mediatorA);
        run(colleagueB1, mediatorA);
        run(colleagueB2, mediatorA);

        // 作業Bに着手
        // B1→B2→Aの順番に作業実施
        // 作業者同士で連携を取ると、runメソッドが2×3=6つ必要になってしまう
        run(colleagueB1, mediatorB);
        run(colleagueB2, mediatorB);
        run(colleagueA, mediatorB);

    }

    // 作業実施メソッド
    public static void run(Colleague colleague, Mediator mediator) {
        colleague.setMediator(mediator);
        if (!colleague.needsAdvice()) {
            colleague.run();
        }
        System.out.println();
    }

}
 
【実行結果】
作業Aは終わりましたか?
まだ作業Aは実施されていません。
作業Aを実施しました。
作業Aの実施ありがとう、作業者Aさん。

作業A終わった?
作業Aはもう作業者Aさんが実施しました。

作業A終わった?
作業Aはもう作業者Aさんが実施しました。

作業B終わった?
作業Bはまだやってないぜ。
作業Bやったよ。
作業Bサンキュー、作業者B1さん。

作業B終わった?
作業Bはもう作業者B1さんがやったよ。

作業Bは終わりましたか?
作業Bはもう作業者B1さんがやったよ。