×

[PR]この広告は3ヶ月以上更新がないため表示されています。
ホームページを更新後24時間以内に表示されなくなります。

C#デザインパターン  - Command

ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。
解説らしい解説は載せていませんので、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』も合わせてお読みください。

※当ソースは、Visual C# 2008 Express Editionで動作を確認しています。
  Visual Studio 2005をお使いの方は、ブログの記事を残しておきますので、そちらをご覧ください。



■ICommand.cs
using System;

namespace Gushwell.DesignPatterns.Command {

public interface ICommand {
void Execute();
}
}


■MacroCommand.cs
using System;
using System.Collections.Generic;
using Gushwell.Dejavu;

namespace Gushwell.DesignPatterns.Command {

// 具体的なCommandには依存しない。
public class MacroCommand : ICommand {
// 命令の集合
private Stack<ICommand> commands = new Stack<ICommand>();

// 実行
public virtual void Execute() {
commands.ForEach(cmd => 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.cs
using System;

namespace Gushwell.DesignPatterns.Drawer {

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


■DrawCommand.cs
using System;
using System.Drawing;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {

// Commandの具象クラス
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);
}
}
}


■DrawCanvas.cs
using System.Drawing;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;

namespace Gushwell.DesignPatterns.Drawer {

// UserControlを継承すると共にう、IDrawableインターフェースを実装する。
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();
}
}
}



■MainForm.cs
using System;
using System.Windows.Forms;
using Gushwell.DesignPatterns.Command;
using Gushwell.DesignPatterns.Drawer;

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

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();
}
}
}


Program .cs
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 MainForm());
}
}
}



EnumerableExtentions .cs
using System;
using System.Collections.Generic;

namespace Gushwell.Dejavu {
public static class EnumerableExtentions {
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
foreach (var x in source) {
action(x);
}
}

public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> func) {
int i = 0;
foreach (var x in source) {
func(x, i);
i++;
}
}
}
}