2006年03月20日

Mediator −相手は相談役1人だけ

  
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。移植後のコードの公開に関しては、結城氏の了解を得ています。
※当ソースは、Visual C# 2005 Express Editionで動作を確認しています。



IColleagueインターフェース
using System;

namespace Gushwell.DesignPatterns {

public interface IColleague {
void SetMediator(IMediator mediator);
void SetColleagueEnabled(bool enabled);
}
}


ColleagueButtonクラス
using System;

namespace Gushwell.DesignPatterns {

[Serializable]
public class ColleagueButton : System.Windows.Forms.Button, IColleague {
private IMediator mediator;
public ColleagueButton()
: base() {
}
// Mediatorを保持
virtual public void SetMediator(IMediator value) {
this.mediator = value;
}

// Mediatorから有効/無効が指示される
virtual public void SetColleagueEnabled(bool value) {
Enabled = value;
}
}
}


ColleagueRadioButtonクラス
using System;

namespace Gushwell.DesignPatterns {

[Serializable]
public class ColleagueRadioButton : System.Windows.Forms.RadioButton, IColleague {
private IMediator mediator = null;
public ColleagueRadioButton()
: base() {
}

// Mediatorを保持
virtual public void SetMediator(IMediator value) {
this.mediator = value;
}

// Mediatorから有効/無効が指示される
virtual public void SetColleagueEnabled(bool value) {
Enabled = value;
}

protected override void OnCheckedChanged(EventArgs e) {
base.OnCheckedChanged(e);
if (mediator != null)
mediator.ColleagueChanged();
}
}
}


ColleagueTextFieldクラス
using System;

namespace Gushwell.DesignPatterns {

[Serializable]
public class ColleagueTextField : System.Windows.Forms.TextBox, IColleague {
private IMediator mediator = null;
public ColleagueTextField()
: base() {
}

// Mediatorを保持
virtual public void SetMediator(IMediator value) {
this.mediator = value;
}

// Mediatorから有効/無効が指示される
virtual public void SetColleagueEnabled(bool value) {
Enabled = value;
}

// 文字列が変化したらMediatorに通知
protected override void OnTextChanged(EventArgs e) {
base.OnTextChanged(e);
if (mediator != null)
mediator.ColleagueChanged();
}
}
}


IMediatorインターフェース
using System;

namespace Gushwell.DesignPatterns {

public interface IMediator {
void CreateColleagues();
void ColleagueChanged();
}
}


LoginFormクラス
using System;
using System.Windows.Forms;

namespace Gushwell.DesignPatterns {
public partial class LoginForm : Form, IMediator {
public LoginForm() {
InitializeComponent();
CreateColleagues();
ColleagueChanged();
}

// 名前が実態と一致しなくなったが、オリジナルの名前のままとする。
public virtual void CreateColleagues() {
checkGuest.SetMediator(this);
checkLogin.SetMediator(this);
textUser.SetMediator(this);
textPass.SetMediator(this);
buttonOk.SetMediator(this);
buttonCancel.SetMediator(this);
}

// Colleageからの通知で各Colleageの有効/無効を判定する。
public virtual void ColleagueChanged() {
if (checkGuest.Checked) {
// Guest mode
textUser.SetColleagueEnabled(false);
textPass.SetColleagueEnabled(false);
buttonOk.SetColleagueEnabled(true);
} else {
// Login mode
textUser.SetColleagueEnabled(true);
UserpassChanged();
}
}
// textUserまたはtextPassの変更があった。
// 各Colleageの有効/無効を判定する。
private void UserpassChanged() {
if (textUser.Text.Length > 0) {
textPass.SetColleagueEnabled(true);
if (textPass.Text.Length > 0) {
buttonOk.SetColleagueEnabled(true);
} else {
buttonOk.SetColleagueEnabled(false);
}
} else {
textPass.SetColleagueEnabled(false);
buttonOk.SetColleagueEnabled(false);
}
}

private void buttonOk_Click(object sender, EventArgs e) {
Console.WriteLine(sender + " : " + e.ToString());
Close();
}
}
}


LoginFormクラス (IDEが作成したソース : LoginForm.Designer.cs)
namespace Gushwell.DesignPatterns {
partial class LoginForm {
private System.ComponentModel.IContainer components = null;

protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}

#region Windows フォーム デザイナで生成されたコード

private void InitializeComponent() {
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.textPass = new ColleagueTextField();
this.textUser = new ColleagueTextField();
this.buttonCancel = new ColleagueButton();
this.buttonOk = new ColleagueButton();
this.checkLogin = new ColleagueRadioButton();
this.checkGuest = new ColleagueRadioButton();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(11, 48);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(58, 12);
this.label1.TabIndex = 2;
this.label1.Text = "Username:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 82);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(56, 12);
this.label2.TabIndex = 3;
this.label2.Text = "Password:";
//
// textPass
//
this.textPass.Location = new System.Drawing.Point(76, 74);
this.textPass.MaxLength = 10;
this.textPass.Name = "textPass";
this.textPass.PasswordChar = '*';
this.textPass.Size = new System.Drawing.Size(118, 19);
this.textPass.TabIndex = 7;
//
// textUser
//
this.textUser.Location = new System.Drawing.Point(75, 41);
this.textUser.MaxLength = 10;
this.textUser.Name = "textUser";
this.textUser.Size = new System.Drawing.Size(119, 19);
this.textUser.TabIndex = 6;
//
// buttonCancel
//
this.buttonCancel.Location = new System.Drawing.Point(110, 117);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(93, 23);
this.buttonCancel.TabIndex = 5;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonOk_Click);
//
// buttonOk
//
this.buttonOk.Location = new System.Drawing.Point(3, 117);
this.buttonOk.Name = "buttonOk";
this.buttonOk.Size = new System.Drawing.Size(101, 23);
this.buttonOk.TabIndex = 4;
this.buttonOk.Text = "OK";
this.buttonOk.UseVisualStyleBackColor = true;
this.buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
//
// checkLogin
//
this.checkLogin.AutoSize = true;
this.checkLogin.Location = new System.Drawing.Point(87, 12);
this.checkLogin.Name = "checkLogin";
this.checkLogin.Size = new System.Drawing.Size(50, 16);
this.checkLogin.TabIndex = 1;
this.checkLogin.TabStop = true;
this.checkLogin.Text = "Login";
this.checkLogin.UseVisualStyleBackColor = true;
//
// checkGuest
//
this.checkGuest.AutoSize = true;
this.checkGuest.Location = new System.Drawing.Point(16, 12);
this.checkGuest.Name = "checkGuest";
this.checkGuest.Size = new System.Drawing.Size(53, 16);
this.checkGuest.TabIndex = 0;
this.checkGuest.TabStop = true;
this.checkGuest.Text = "Guest";
this.checkGuest.UseVisualStyleBackColor = true;
//
// LoginForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(206, 146);
this.Controls.Add(this.textPass);
this.Controls.Add(this.textUser);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonOk);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.checkLogin);
this.Controls.Add(this.checkGuest);
this.Name = "LoginForm";
this.Text = "Mediator Sample";
this.ResumeLayout(false);
this.PerformLayout();

}

#endregion

private ColleagueRadioButton checkGuest;
private ColleagueRadioButton checkLogin;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private ColleagueButton buttonOk;
private ColleagueButton buttonCancel;
private ColleagueTextField textUser;
private ColleagueTextField textPass;

}
}


Programクラス
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Gushwell.DesignPatterns {
static class Program {
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
}
}
}


注意点:
ColleagueButton、ColleagueRadioButton、ColleagueTextField の3つのクラスをプロジェクトに追加するとツールボックスにこれら3つのコントロールが追加されますので、このコントロールを使って、以下の画面を参考に、フォームをデザインしてください。


 

この記事へのトラックバックURL