Skeleton of GOF's Design Pattern


MEDIATORの骸骨

MEDIATOR

このパターンは、一つの大きな台紙(コンテナ)に複数のオブジェクトを貼り付けて、台紙(コンテナ)上でそれらの関連を記述するパターンです。

よく似たパターンに OBSERVER がありますが、OBSERVER はオブジェクトの状態の一貫性に着目しているのに対し、MEDIATOR は、部品オブジェクトが発生するイベントに着目したパターンと言えると思います。


■ 『MEDIATORの骸骨』の構造


■ 『MEDIATORの骸骨』の特徴的な協調関係


■ 『MEDIATORの骸骨』 プログラム・コード

□ Java2版
// Copyright(C) 2000-2003 Yoshinori Oota All rights reserved.

import java.awt.*;
import java.awt.event.*;

public class MediatorSample { 
    static public void main(String[] args) { 
        CanvasMediator mediator = new CanvasMediator(); 
    } 
}

abstract class Mediator {
    abstract public void ColleagueChanged(Colleague colleague); 
}

class CanvasMediator extends Mediator { 
    private BrighterColleague _brighter = null;
    private DarkerColleague _darker = null;
    private Frame _frame = new Frame("Mediator Sample");
    private Color  _color = new Color(128, 128, 128);

    public CanvasMediator() { 
        _brighter = new BrighterColleague(this);
        _darker = new DarkerColleague(this);
        _frame.setSize(200, 200);
        _frame.setBackground(_color);
        _frame.show();
    } 
    public void ColleagueChanged(Colleague colleague) {
        if (_brighter.equals(colleague)) {
            _color = _color.brighter();
            _frame.setBackground(_color);
        } else if (_darker.equals(colleague)) {
            _color = _color.darker();
            _frame.setBackground(_color);
        }
    }
    void add(String pos, Button collegue) {
        _frame.add(pos, collegue);
    }
}

abstract class Colleague {
    private Mediator _mediator = null;
    public Colleague(Mediator mediator) {
        _mediator = mediator;
    }
    void Changed() { 
        _mediator.ColleagueChanged(this); 
    } 
}

class BrighterColleague extends Colleague implements ActionListener { 
    private Button _button = new Button("Brighter");

    public BrighterColleague(CanvasMediator mediator) { 
        super(mediator);
        mediator.add("North", _button);
        _button.addActionListener(this);
    }
    public void actionPerformed(ActionEvent event) {
        Changed();
    }
}

class DarkerColleague extends Colleague implements ActionListener { 
    private Button _button = new Button("Darker");

    public DarkerColleague(CanvasMediator mediator) { 
        super(mediator);
        mediator.add("South", _button);
        _button.addActionListener(this);
    }
    public void actionPerformed(ActionEvent event) {
        Changed();
    }
}

○ C++版
// Copyright(C) 2003 Yoshinori Oota All rights reserved.

#include <iostream>
using namespace std;

class Mediator;

class Colleague {
public:
    Colleague(Mediator* m);
    virtual ~Colleague();
    virtual void actionPerformed(char key_event) = 0;
protected:
    void Changed();
private:
    Mediator* mediator_;
};

class BrighterColleague : public Colleague {
public:
    BrighterColleague(Mediator* m);
    virtual ~BrighterColleague();
    virtual void actionPerformed(char key_event);
};

class DarkerColleague : public Colleague {
public:
    DarkerColleague(Mediator* m);
    virtual ~DarkerColleague();
    virtual void actionPerformed(char key_event);
};

class Mediator {
public:
    Mediator();
    virtual ~Mediator();
    virtual void ColleagueChanged(Colleague* c) = 0;
};

class CanvasMediator : public Mediator { 
public:
    CanvasMediator();
    virtual ~CanvasMediator();
    virtual void ColleagueChanged(const Colleague* colleague);
    bool event(char key);
protected:
    void WriteCanvas(int color);
private:
    BrighterColleague* brighter_;
    DarkerColleague* darker_;
    int color_;
};


Mediator::Mediator() { }
Mediator::~Mediator() { }

CanvasMediator::CanvasMediator() :
  brighter_(new BrighterColleague(this)),
  darker_(new DarkerColleague(this)), 
  color_(44) {
    WriteCanvas(color_);
}
CanvasMediator::~CanvasMediator() {
    delete brighter_;
    delete darker_;
}
bool CanvasMediator::event(char key) {
    if (key != 'H' && key != 'L') return false;
    brighter_->actionPerformed(key);
    darker_->actionPerformed(key);
    return true;
}
void CanvasMediator::WriteCanvas(int color) {
    cout << "\e[2J";                            // 画面クリア
    cout << "\e[4;0H";                          // 4行0列目にカーソルセット 
    if (color_ != 47) {
         cout << "\e[37;" << color << "m"       // 前景:白 背景:colorにセット 
         << "Mediator Sample(" << color << ")";
    } else {
         cout << "\e[30;" << color << "m"       // 前景:黒 背景:colorにセット 
         << "Mediator Sample(" << color << ")";
    }
    cout << "\e[0m" << endl;                    // 色の設定をデフォルトに戻す
    cout.flush();
}
void CanvasMediator::ColleagueChanged(const Colleague* colleague) {
    if (colleague == brighter_) {
      color_ >= 47 ? color_ : ++color_; 
    } else if (colleague == darker_) {
      color_ <= 40 ? color_ : --color_; 
    }
    WriteCanvas(color_);
}

Colleague::Colleague(Mediator* m) : mediator_(m) { }
Colleague::~Colleague() { }
void Colleague::Changed() { 
    mediator_->ColleagueChanged(this); 
} 

BrighterColleague::BrighterColleague(Mediator* m) : Colleague(m) { }
BrighterColleague::~BrighterColleague() { }
void BrighterColleague::actionPerformed(char key_event) {
    if ('H' == key_event) {
        Changed();
    }
}

DarkerColleague::DarkerColleague(Mediator* m) : Colleague(m) { }
DarkerColleague::~DarkerColleague() { }
void DarkerColleague::actionPerformed(char key_event) {
    if ('L' == key_event) {
        Changed();
    }
}


int main() {
    char key[5];
    bool run = true;
    CanvasMediator* mediator = new CanvasMediator(); 

    while (run) {
        cout << "Input Key: ";
        cin.getline(key, 5);
        run = mediator->event(key[0]);
    }
    delete mediator;
}

○ C版
/* Copyright(C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>

struct Mediator;
enum COLLEAGUE_TYPE { BRIGHTER, DARKER };

/* Colleague Interface */
struct Colleague {
    enum COLLEAGUE_TYPE type_;
    struct Mediator* mediator_;
    void (*actionPerformed)(struct Colleague* pthis ,char key_event);
    void (*Changed)(struct Colleague* pthis);
};
struct Colleague* New_Colleague(enum COLLEAGUE_TYPE type ,struct Mediator* m);
void Delete_Colleague(struct Colleague* colleague);
void Colleague_Changed(struct Colleague* pthis);
void BrighterColleague_actionPerformed(struct Colleague* pthis ,char key_event);
void DarkerColleague_actionPerformed(struct Colleague* pthis ,char key_event);


/* Mediator Interface */
struct Mediator {
    struct Colleague* brighter_;
    struct Colleague* darker_;
    int color_;
    void (*ColleagueChanged)(struct Mediator* pthis ,struct Colleague* colleague);
    int (*Event)(struct Mediator* pthis ,char key);
};
struct Mediator* New_Mediator();
void Delete_Mediator(struct Mediator* c);
int Mediator_event(struct Mediator* pthis ,char key);
void CanvasMediator_ColleagueChanged(struct Mediator* pthis ,struct Colleague* c);
void CanvasMediator_private_WriteCanvas(struct Mediator* pthis ,int color);


/* Colleague Class Implementation */
struct Colleague* New_Colleague(enum COLLEAGUE_TYPE type ,struct Mediator* mediator) {
    struct Colleague* colleague = (struct Colleague*)malloc(sizeof(struct Colleague));
    colleague->type_ = type;
    colleague->mediator_ = mediator;
    colleague->Changed = &Colleague_Changed;
    switch (type) {
    case BRIGHTER:
        colleague->actionPerformed = &BrighterColleague_actionPerformed;
        break;
    case DARKER:
        colleague->actionPerformed = &DarkerColleague_actionPerformed;
        break;
    }
    return colleague;
}

void Delete_Colleague(struct Colleague* colleague) {
    if (colleague == NULL) {
        return;
    }
    free(colleague);
    colleague = NULL;
    return;
}

void Colleague_Changed (struct Colleague* pthis) { 
    pthis->mediator_->ColleagueChanged(pthis->mediator_ ,pthis); 
    return;
} 

void BrighterColleague_actionPerformed(struct Colleague* pthis ,char key_event) {
    if ('H' == key_event) { 
        pthis->Changed(pthis);
    }
    return;
}

void DarkerColleague_actionPerformed(struct Colleague* pthis ,char key_event) {
    if ('L' == key_event) {
        pthis->Changed(pthis);
    }
    return;
}

/* Mediator Class Implementation */
struct Mediator* New_Mediator() {
    struct Mediator* mediator = NULL;
    mediator = (struct Mediator*)malloc(sizeof(struct Mediator));
    mediator->brighter_ = New_Colleague(BRIGHTER ,mediator);
    mediator->darker_ = New_Colleague(DARKER ,mediator);
    mediator->color_ = 44;
    mediator->ColleagueChanged = &CanvasMediator_ColleagueChanged;
    mediator->Event = &Mediator_event;
    return mediator;
}

void Delete_Mediator(struct Mediator* mediator) {
    if (mediator == NULL) {
        return;
    }
    free(mediator->brighter_);
    mediator->brighter_ = NULL;
    free(mediator->darker_);
    mediator->darker_ = NULL;
    free(mediator);
    mediator = NULL;
    return;
}

int Mediator_event(struct Mediator* pthis ,char key) {
    if (key != 'H' && key != 'L') {
        return 0;
    }
    pthis->brighter_->actionPerformed(pthis->brighter_ ,key);
    pthis->darker_->actionPerformed(pthis->darker_ ,key);
    return 1;
}

void CanvasMediator_private_WriteCanvas(struct Mediator* pthis ,int color) {
     printf("\e[2J");                      // 画面クリア
     printf("\e[4;0H");                    // 4行0列目にカーソルセット 
     if (pthis->color_ != 47) {
         printf("\e[37;%dm" ,color);       // 前景:白 背景:colorにセット 
         printf("Mediator Sample(%d)" ,color);
     } else {
         printf("\e[30;%dm" ,color);       // 前景:黒 背景:colorにセット 
         printf("Mediator Sample(%d)" ,color);
     }
     printf("\e[0m\n");                    // 色の設定をデフォルトに戻す
     return;
}

void CanvasMediator_ColleagueChanged(struct Mediator* pthis ,struct Colleague* colleague) {
     if (colleague->type_ == BRIGHTER) {
         pthis->color_ >= 47 ? pthis->color_ : pthis->color_++; 
     } else if (colleague->type_ == DARKER) {
         pthis->color_ <= 40 ? pthis->color_ : pthis->color_--; 
     }
     CanvasMediator_private_WriteCanvas(pthis ,pthis->color_);
     return;
}

int main() {
     char key[5];
     int run = 1;
     struct Mediator* mediator = NULL;

     mediator = New_Mediator(); 

     while (run) {
        printf ("Input Key: ");
        fgets(key ,4 ,stdin);
        key[4] = '\0';
        run = mediator->Event(mediator ,key[0]);
     }

     Delete_Mediator (mediator);

     return 0;
}


改訂履歴

2009.2.22 C言語版を追加
     
     

ご意見、ご感想はこちらまで。

Copyright(C) 2000-2009 Yoshinori Oota All rights reserved.

本ホームページのリンクは自由です。複製、転載される場合は、必ず著者までご連絡をください。