2013年7月24日 星期三

設計模式:中介者模式 (Mediator Pattern)

中介者模式 (Mediator Pattern),以下程式碼以 C# 為例

說明:
當物件和物件之間或有錯綜複雜的交互作用,可將這些關係交由另一物件(中介者)來處理,
以減少這些物件間的耦合。

範例:
有一個醫護兵物件、一個步兵物件(屬於同事物件),能發出不同的訊息,
中介者物件則負責這些訊息要如何處理、要再傳遞給誰。

希望達成如下的效果
static void Main(string[] args)
{
    ConcreteMediator mediator = new ConcreteMediator(); // 中介者

    MedicColleague medic = new MedicColleague("小護士", mediator); // 醫護兵
    InfantryColleague infantry = new InfantryColleague("小小強", mediator); // 步兵

    medic.Send("normal", "吹東風了");
    infantry.Send("normal", "左前方一隻小白兔走過去");
    medic.Send("attack", "遭受敵人攻擊");
    infantry.Send("hurt", "我中彈了");

    Console.Read();
}
執行結果: 
中介者 接收到 小護士 訊息:吹東風了 => 訊息處理
小小強 接收到 小護士 訊息:吹東風了
中介者 接收到 小小強 訊息:左前方一隻小白兔走過去 => 訊息處理
小護士 接收到 小小強 訊息:左前方一隻小白兔走過去
中介者 接收到 小護士 訊息:遭受敵人攻擊 => 訊息處理
小小強 接收到 小護士 訊息:遭受敵人攻擊。前往救助中
中介者 接收到 小小強 訊息:我中彈了 => 訊息處理
小護士 接收到 小小強 訊息:我中彈了。前往救護中

實現重點在於,同事物件(醫護兵物件、步兵物件)發出訊息時,其實是丟給中介者物件,再由中介者物件負責訊息要再傳遞給誰。

其餘程式碼
// 中介者抽像類別
abstract class Mediator
{
    protected MedicColleague medic; // 醫護兵
    protected InfantryColleague infantry; // 步兵

    // 設定醫護兵
    public MedicColleague Medic
    {
        set { medic = value; }
    }

    // 設定步兵
    public InfantryColleague Infantry
    {
        set { infantry = value; }
    }
    public abstract void Work(string msgType, string msgCon, Colleague colleague);
}

// 中介者
class ConcreteMediator : Mediator
{

    // 中介者處理接收到的訊息
    public override void Work(string msgType, string msgCon, Colleague colleague)
    {
        Console.WriteLine("中介者 接收到 {0} 訊息:{1} => 訊息處理", colleague.Name, msgCon);
        switch (msgType)
        {
            case "hurt":
                this.medic.Action(msgCon, colleague);
                break;
            case "attack":
                this.infantry.Action(msgCon, colleague);
                break;
            case "normal":
                if (colleague != this.medic) this.medic.Receive(msgCon, colleague);
                if (colleague != this.infantry) this.infantry.Receive(msgCon, colleague);
                break;
        }
    }
}

// 同事抽象類別
abstract class Colleague
{
    protected string name; // 姓名

    protected Mediator mediator; // 中介者

    // 設定姓名、中介者
    public Colleague(string name, Mediator mediator)
    {
        this.name = name;
        this.mediator = mediator;
    }

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    // 發送訊息給中介者
    public void Send(string msgType, string msgCon)
    {
        mediator.Work(msgType, msgCon, this);
    }

    // 接收一般訊息
    public void Receive(string msgCon, Colleague colleague)
    {
        Console.WriteLine("{0} 接收到 {1} 訊息:{2}", this.name, colleague.Name, msgCon);
    }
}

// 醫護兵
class MedicColleague : Colleague
{
    public MedicColleague(string name, Mediator mediator)
        : base(name, mediator)
    {
        mediator.Medic = this;
    }

    // 醫療行動
    public void Action(string msgCon, Colleague colleague)
    {
        Console.WriteLine("{0} 接收到 {1} 訊息:{2}。前往救護中", this.name, colleague.Name, msgCon);
    }
}

// 步兵
class InfantryColleague : Colleague
{
    public InfantryColleague(string name, Mediator mediator)
        : base(name, mediator)
    {
        mediator.Infantry = this;
    }

    // 攻擊行動
    public void Action(string msgCon, Colleague colleague)
    {
        Console.WriteLine("{0} 接收到 {1} 訊息:{2}。前往救助中", this.name, colleague.Name, msgCon);
    }
}

相關連結:設計模式整理列表

沒有留言:

張貼留言