2006年04月19日

Command ― 命令をクラスにする

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



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

namespace Gushwell.DesignPatterns.Command {

public interface ICommand {
void Execute();
}
}


DrawCommandクラス
using System;
using System.Drawing;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {

public class DrawCommand : ICommand {
// 描画対象
protected internal IDrawable drawable;

// 描画位置
private System.Drawing.Point position;

// コンストラクタ
public DrawCommand(IDrawable drawable, Point position) {
this.drawable = drawable;
this.position = position;
}

// 実行
public virtual void Execute() {
drawable.Draw(position.X, position.Y);
}
}
}


MacroCommandクラス
using System;
using System.Collections;

namespace Gushwell.DesignPatterns.Command {

public class MacroCommand : ICommand {
// 命令の集合
private Stack commands = new Stack();

// 実行
public virtual void Execute() {
foreach (ICommand cmd in commands) {
cmd.Execute();
}
}

// 追加
public virtual void Append(ICommand cmd) {
if (cmd != this) {
commands.Push(cmd);
}
}

// 最後の命令を削除
public virtual void Undo() {
if (!(commands.Count == 0)) {
commands.Pop();
}
}

// 全部削除
public virtual void Clear() {
commands.Clear();
}
}
}



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

namespace Gushwell.DesignPatterns.Drawer {

public interface IDrawable {
void Draw(int x, int y);
}
}



DrawCanvasクラス
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {
public partial class DrawCanvas : UserControl, IDrawable {
public DrawCanvas() {
InitializeComponent();
}
// 描画色
private Color color = Color.Red;
// 描画する点の半径
private int radius = 6;
// 履歴
private MacroCommand history = null;

public void Draw(int x, int y) {
using ( Graphics g = CreateGraphics() )
using ( Brush brush = new SolidBrush(color) ) {
g.FillEllipse(brush, x - radius, y - radius, radius * 2, radius * 2);
}
}
public void SetHistory(MacroCommand history) {
this.history = history;
}

private void DrawCanvas_Paint(object sender, PaintEventArgs e) {
if (history != null)
history.Execute();
}
}
}



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

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

#region コンポーネント デザイナで生成されたコード

/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.SuspendLayout();
//
// DrawCanvas
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "DrawCanvas";
this.Paint +=
new System.Windows.Forms.PaintEventHandler(this.DrawCanvas_Paint);
this.ResumeLayout(false);

}

#endregion
}
}



Form1クラス
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;
using Gushwell.DesignPatterns.Drawer;

namespace Gushwell.DesignPatterns {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
drawCanvas1.SetHistory(history);
}

private void Form1_MouseDown(object sender, MouseEventArgs e) {
//userControl11.draw(e.X, e.Y);
}
private MacroCommand history = new MacroCommand();

private bool drag = false;
private void drawCanvas1_MouseDown(object sender, MouseEventArgs e) {
drag = true;

}

private void drawCanvas1_MouseMove(object sender, MouseEventArgs e) {
if (drag) {
ICommand cmd = new DrawCommand(drawCanvas1, e.Location);
history.Append(cmd);
cmd.Execute();
}
}

private void drawCanvas1_MouseUp(object sender, MouseEventArgs e) {
drag = false;
}

private void clearButton_Click(object sender, EventArgs e) {
history.Clear();
drawCanvas1.Invalidate();
}
}
}



Form1クラス (IDEが作成したソース : Form1.Designer.cs)
using Gushwell.DesignPatterns.Drawer;

namespace Gushwell.DesignPatterns {
partial class Form1 {
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.clearButton = new System.Windows.Forms.Button();
this.drawCanvas1 = new Gushwell.DesignPatterns.Drawer.DrawCanvas();
this.SuspendLayout();
//
// clearButton
//
this.clearButton.Location = new System.Drawing.Point(104, 3);
this.clearButton.Name = "clearButton";
this.clearButton.Size = new System.Drawing.Size(75, 23);
this.clearButton.TabIndex = 1;
this.clearButton.Text = "Clear";
this.clearButton.UseVisualStyleBackColor = true;
this.clearButton.Click += new System.EventHandler(this.clearButton_Click);
//
// drawCanvas1
//
this.drawCanvas1.BackColor = System.Drawing.SystemColors.Window;
this.drawCanvas1.Location = new System.Drawing.Point(1, 32);
this.drawCanvas1.Name = "drawCanvas1";
this.drawCanvas1.Size = new System.Drawing.Size(290, 239);
this.drawCanvas1.TabIndex = 0;
this.drawCanvas1.MouseDown +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseDown);
this.drawCanvas1.MouseMove +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseMove);
this.drawCanvas1.MouseUp +=
new System.Windows.Forms.MouseEventHandler(this.drawCanvas1_MouseUp);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.clearButton);
this.Controls.Add(this.drawCanvas1);
this.Name = "Form1";
this.Text = "Command Pattern Sample";
this.MouseDown +=
new System.Windows.Forms.MouseEventHandler(this.Form1_MouseDown);
this.ResumeLayout(false);

}

#endregion

private DrawCanvas drawCanvas1;
private System.Windows.Forms.Button clearButton;
}
}


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

namespace Gushwell.DesignPatterns {
static class Program {
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}



 

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

http://trackback.blogsys.jp/livedoor/gushwell/50431093