Dyuichi Blog

オブジェクト指向シリーズⅣ: デザインパターン [⑯ Mediator]

概要

mediatorは日本語で「仲裁人」,「調停者」という意味になる.Mediatorパターンは,オブジェクト群の相互作用をカプセル化するオブジェクトを定義することで,オブジェクトが直接互いに参照しないようにし,独立して再利用できるようにするパターンである.

Mediatorパターンの主な要素は以下である.

  • Mediator:Colleague間で通信するためのオブジェクトのインターフェース
  • ConcreteMediator:Mediatorを実装したクラス
  • Colleague:Mediatorを介して通信するオブジェクトのインターフェース
  • ConcreteColleague:Colleagueを実装したクラス

クラス図

画像が読み込まれない場合はページを更新してみてください。

実装例(Java)

javaimport java.util.ArrayList;
import java.util.List;

// Mediator
interface Mediator {
    void register(Colleague colleague);
    void relay(Colleague colleague);
}

// Concrete Mediator
class ConcreteMediator implements Mediator {
    private List<Colleague> colleagues = new ArrayList<>();
    @Override
    public void register(Colleague colleague) {
        if (!colleagues.contains(colleague)) {
            colleagues.add(colleague);
            colleague.setMediator(this);
        }
    }
    @Override
    public void relay(Colleague colleague) {
        for (Colleague ob : colleagues) {
            if (!ob.equals(colleague)) {
                ((Colleague) ob).receive();
            }
        }
    }
}

// Colleague
abstract class Colleague {
    protected Mediator mediator;
    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }
    public abstract void receive();
    public abstract void send();
}

// Concrete Colleague
class ConcreteColleagueA extends Colleague {
    @Override
    public void receive() {
        System.out.println("ConcreteColleagueA receive");
    }
    @Override
    public void send() {
        System.out.println("ConcreteColleagueA send");
        mediator.relay(this);
    }
}

class ConcreteColleagueB extends Colleague {
    @Override
    public void receive() {
        System.out.println("ConcreteColleagueB receive");
    }
    @Override
    public void send() {
        System.out.println("ConcreteColleagueB send");
        mediator.relay(this);
    }
}

// Client
public class MediatorPattern {
    public static void main(String[] args) {
        Mediator mediator = new ConcreteMediator();
        Colleague colleagueA = new ConcreteColleagueA();
        Colleague colleagueB = new ConcreteColleagueB();
        mediator.register(colleagueA);
        mediator.register(colleagueB);
        colleagueA.send();
        colleagueB.send();
    }
}

まとめ,所感

P2Pのような構造(いや,Mediatorを介すからP2Pではない)ROS1みたいな構造(Mediatorがroscore)を実装したいときに便利.ROSを知らない人には伝わらなくてすみませんが,個人的にROS1が一番しっくり来てしまいました…

クライアントとColleagueオブジェクトを実装する際は,他の要素をあまり意識する必要が無い.

しかし,Mediatorの実装が複雑になりがちだなと感じた.実装例は非常に単純なものだったので,まだ理解できたが,もっと複雑なプログラムになってくるとMediatorの読解・実装が困難になり,バグを生みやすくなりそう.

Mediatorに対してまた別のデザインパターンを適用して改善できたらいいかもしれない(いや,もっと複雑になってしまうかも?).