まさるblog

越後在住子持ちプログラマー奮闘記 - Author:まさる(高野 将、TAKANO Sho)

目次

Blog 利用状況

ニュース

著書

2010/7発売


Web掲載記事

@IT

.NET開発を始めるVB6プログラマーが知るべき9のこと

CodeZine

実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント

第1回 3層データバインドを正しく活用しよう(前編)

ブログパーツ


書庫

日記カテゴリ

コミュニティ

デザインパターンを学ぶ~その21:Commandパターン(1)~

Command

命令

Commandパターンは、「命令」をオブジェクトとして扱うパターンです。これにより「命令」を呼び出す側は、その「命令」が実際どのように動作するか気にする必要がなくなります。

 

このパターンの概要は以下の通り。

  1. 「命令」を実行するメソッドExecuteをもつインターフェイスを定義します。
    C#
    public interface ICommand
    {
      void Execute();
    }
    

    VB
    Public Interface ICommand
      Sub Execute()
    End Interface
    
  2. 「命令」を受け取るクラス、Recieverを定義します。RecieverはどんなクラスでもOKです。コード例ではLightにしました。
    C#
    public class Light
    {
      private enum State
      {
        On
        , Off
      }
    
      private State state = State.Off;
    
      public void On()
      {
        this.state = State.On;
        Console.WriteLine("ライトが点きました");
      }
    
      public void Off()
      {
        this.state = State.Off;
        Console.WriteLine("ライトが消えました");
      }
    
      public void DisplayState()
      {
        if (this.state == State.On)
        {
          Console.WriteLine("ライトは点いています");
        }
        else
        {
          Console.WriteLine("ライトは消えています");
        }
      }
    }
    

    VB
    Public Class Light
    
      Private Enum PowerState
        [On]
        Off
      End Enum
    
      Private state As PowerState = PowerState.Off
    
      Public Sub [On]()
        Me.state = PowerState.On
        Console.WriteLine("ライトが点きました")
      End Sub
    
      Public Sub Off()
        Me.state = PowerState.Off
        Console.WriteLine("ライトが消えました")
      End Sub
    
      Public Sub DisplayState()
        If Me.state = PowerState.On Then
          Console.WriteLine("ライトは点いています")
        Else
          Console.WriteLine("ライトは消えています")
        End If
      End Sub
    
    End Class
    
  3. 実際にRecieverに対しての命令をICommandを実装したクラスとして定義します。コード例ではLightのOn、OffそれぞれのCommandを定義しています。
    C#
    public class LightOnCommand : ICommand
    {
      private Light light;
    
      public LightOnCommand(Light light)
      {
        this.light = light;
      }
    
      public void Execute()
      {
        this.light.On();
      }
    }
    
    public class LightOffCommand : ICommand
    {
      private Light light;
    
      public LightOffCommand(Light light)
      {
        this.light = light;
      }
    
      public void Execute()
      {
        this.light.Off();
      }
    }
    

    VB
    Public Class LightOnCommand
      Implements ICommand
    
      Private light As Light
    
      Public Sub New(ByVal light As Light)
        Me.light = light
      End Sub
    
      Public Sub Execute() Implements ICommand.Execute
        Me.light.On()
      End Sub
    
    End Class
    
    Public Class LightOffCommand
      Implements ICommand
    
      Private light As Light
    
      Public Sub New(ByVal light As Light)
        Me.light = light
      End Sub
    
      Public Sub Execute() Implements ICommand.Execute
        Me.light.Off()
      End Sub
    
    End Class
    
  4. Commandを登録して、実際に起動するInvokerを定義します。コード例ではRemoteControllerとして、On、OffそれぞれのCommandを登録できるようにしています。
    C#
    public class RemoteController
    {
      private ICommand onCommand;
      public ICommand OnCommand
      {
        set
        {
          this.onCommand = value;
        }
      }
    
      private ICommand offCommand;
      public ICommand OffCommand
      {
        set
        {
          this.offCommand = value;
        }
      }
    
      public void OnButtonWasPressed()
      {
        if (this.onCommand == null)
        {
          return;
        }
        this.onCommand.Execute();
      }
    
      public void OffButtonWasPressed()
      {
        if (this.offCommand == null)
        {
          return;
        }
        this.offCommand.Execute();
      }
    }
    

    VB
    Public Class RemoteController
    
      Private _onCommand As ICommand
      Public WriteOnly Property OnCommand() As ICommand
        Set(ByVal value As ICommand)
          Me._onCommand = value
        End Set
      End Property
    
      Private _offCommand As ICommand
      Public WriteOnly Property OffCommand() As ICommand
        Set(ByVal value As ICommand)
          _offCommand = value
        End Set
      End Property
    
      Public Sub OnButtonWasPressed()
        If Me._onCommand Is Nothing Then
          Return
        End If
        Me._onCommand.Execute()
      End Sub
    
      Public Sub OffButtonWasPressed()
        If Me._offCommand Is Nothing Then
          Return
        End If
        Me._offCommand.Execute()
      End Sub
    
    End Class
    

実行してみましょう。Clientでは次のようにCommandを使用します。

C#

public class Program
{
  public static void Main(string[] args)
  {
    // Invokerのインスタンス作成
    RemoteController remoCon = new RemoteController();

    Console.WriteLine("■Lightに対してCommand実行");

    // Reciever:Lightのインスタンス作成
    Light light = new Light();

    light.DisplayState();

    // Light用Command作成
    LightOnCommand lightOnCommand = new LightOnCommand(light);
    LightOffCommand lightOffCommand = new LightOffCommand(light);

    // Light用CommandをInvokerに設定
    remoCon.OnCommand = lightOnCommand;
    remoCon.OffCommand = lightOffCommand;

    // InvokerよりOnCommand実行
    remoCon.OnButtonWasPressed();

    light.DisplayState();

    // InvokerよりOffCommand実行
    remoCon.OffButtonWasPressed();

    light.DisplayState();

    Console.ReadKey();
  }
}

VB

Public Class Program

  Public Shared Sub Main(ByVal args As String())
    ' Invokerのインスタンス作成
    Dim remoCon As New RemoteController()

    Console.WriteLine("■Lightに対してCommand実行")

    ' Reciever:Lightのインスタンス作成
    Dim light As New Light()

    light.DisplayState()

    ' Light用Command作成
    Dim lightOnCommand As New LightOnCommand(light)
    Dim lightOffCommand As New LightOffCommand(light)

    ' Light用CommandをInvokerに設定
    remoCon.OnCommand = lightOnCommand
    remoCon.OffCommand = lightOffCommand

    ' InvokerよりOnCommand実行
    remoCon.OnButtonWasPressed()

    light.DisplayState()

    ' InvokerよりOffCommand実行
    remoCon.OffButtonWasPressed()

    light.DisplayState()

    Console.ReadKey()
  End Sub

End Class

 

上記のクラス、インターフェイスの関連をクラス図で現わすと、次のようになります。

Commandパターンクラス図

 

それでは、コードを実行してみましょう。

image

ClientはInvokerに登録されたCommandを通して、Recieverの動作を呼び出していることがわかります。

 

そして、Commandを入れ替えれば、他のRecieverに対しても処理を行うことが可能です。

例えばCDPlayerに対する処理を行うとして、次のようにReciever、Commandを新たに作成し、Clientのコードを変更します。このとき、Invoker、すでに作成されたCommandへの変更を行う必要はありません。

C#

public class CDPlayer
{
  enum State
  {
    Play
    , Stop
  }

  private State state = State.Stop;

  public void Play()
  {
    this.state = State.Play;
    Console.WriteLine("CDが再生されました");
  }

  public void Stop()
  {
    this.state = State.Stop;
    Console.WriteLine("CDが停止されました");
  }

  public void DisplayState()
  {
    if (this.state == State.Play)
    {
      Console.WriteLine("CDは再生中です");
    }
    else
    {
      Console.WriteLine("CDは停止中です");
    }
  }
}

public class CDPlayerPlayCommand : ICommand
{
  private CDPlayer player;

  public CDPlayerPlayCommand(CDPlayer player)
  {
    this.player = player;
  }

  #region ICommand メンバ

  public void Execute()
  {
    this.player.Play();
  }

  #endregion
}

public class CDPlayerStopCommand : ICommand
{
  private CDPlayer player;

  public CDPlayerStopCommand(CDPlayer player)
  {
    this.player = player;
  }

  #region ICommand メンバ

  public void Execute()
  {
    this.player.Stop();
  }

  #endregion
}

public class Program
{
  public static void Main(string[] args)
  {
    // Invokerのインスタンス作成
    RemoteController remoCon = new RemoteController();

    Console.WriteLine("■CDPlayerに対してCommand実行");

    // Reciever:CDPlayerのインスタンス作成
    CDPlayer player = new CDPlayer();

    player.DisplayState();

    // CDPlayer用Command作成
    CDPlayerPlayCommand playCommand = new CDPlayerPlayCommand(player);
    CDPlayerStopCommand stopCommand = new CDPlayerStopCommand(player);

    // CDPlaer用CommandをInvokerに設定
    remoCon.OnCommand = playCommand;
    remoCon.OffCommand = stopCommand;

    // InvokerよりOnCommand実行
    remoCon.OnButtonWasPressed();

    player.DisplayState();

    // InvokerよりOffCommand実行
    remoCon.OffButtonWasPressed();

    player.DisplayState();


    Console.ReadKey();
  }
}

VB
Public Class CDPlayer

  Private Enum BehaviorState
    Play
    [Stop]
  End Enum

  Private state As BehaviorState = BehaviorState.[Stop]

  Public Sub Play()
    Me.state = BehaviorState.Play
    Console.WriteLine("CDが再生されました")
  End Sub

  Public Sub [Stop]()
    Me.state = BehaviorState.[Stop]
    Console.WriteLine("CDが停止されました")
  End Sub

  Public Sub DisplayState()
    If Me.state = BehaviorState.Play Then
      Console.WriteLine("CDは再生中です")
    Else
      Console.WriteLine("CDは停止中です")
    End If
  End Sub

End Class

Public Class CDPlayerPlayCommand
  Implements ICommand

  Private player As CDPlayer

  Public Sub New(ByVal player As CDPlayer)
    Me.player = player
  End Sub

  Public Sub Execute() Implements ICommand.Execute
    Me.player.Play()
  End Sub

End Class

Public Class CDPlayerStopCommand
  Implements ICommand

  Private player As CDPlayer

  Public Sub New(ByVal player As CDPlayer)
    Me.player = player
  End Sub

  Public Sub Execute() Implements ICommand.Execute
    Me.player.Stop()
  End Sub

End Class

Public Class Program

  Public Shared Sub Main(ByVal args As String())
    ' Invokerのインスタンス作成
    Dim remoCon As New RemoteController()

    Console.WriteLine("■CDPlayerに対してCommand実行")

    ' Reciever:CDPlayerのインスタンス作成
    Dim player As New CDPlayer()

    player.DisplayState()

    ' CDPlayer用Command作成
    Dim playCommand As New CDPlayerPlayCommand(player)
    Dim stopCommand As New CDPlayerStopCommand(player)

    ' Light用CommandをInvokerに設定
    remoCon.OnCommand = playCommand
    remoCon.OffCommand = stopCommand

    ' InvokerよりOnCommand実行
    remoCon.OnButtonWasPressed()

    player.DisplayState()

    ' InvokerよりOffCommand実行
    remoCon.OffButtonWasPressed()

    player.DisplayState()

    Console.ReadKey()
  End Sub

End Class

image

CDPlayerの動作に変更されたことが確認できました。

 

さて、以上がCommandパターンの基本形です。

次回は、複数のCommandをまとめて呼び出す方法について紹介します。

投稿日時 : 2008年11月21日 23:40

Feedback

# デザインパターンを学ぶ~その22:Commandパターン(2)~ 2009/01/06 22:55 まさるblog

デザインパターンを学ぶ~その22:Commandパターン(2)~

# My partner and I stumbled over here coming from a different website and thought I might as well check things out. I like what I see so i am just following you. Look forward to looking over your web page yet again. 2018/10/06 23:33 My partner and I stumbled over here coming from a

My partner and I stumbled over here coming from a different website and thought I might as well check things out.
I like what I see so i am just following you.
Look forward to looking over your web page yet again.

# Why viewers still make use of to read news papers when in this technological globe all is accessible on net? 2018/10/08 6:21 Why viewers still make use of to read news papers

Why viewers still make use of to read news papers when in this
technological globe all is accessible on net?

# I just couldn't leave your web site before suggesting that I actually enjoyed the standard info a person provide to your visitors? Is gonna be back ceaselessly in order to check out new posts 2018/10/11 20:00 I just couldn't leave your web site before suggest

I just couldn't leave your web site before suggesting that I actually enjoyed the standard info a person provide
to your visitors? Is gonna be back ceaselessly in order to check
out new posts

# Post writing is also a fun, if you know then you can write if not it is complex to write. 2018/11/10 21:41 Post writing is also a fun, if you know then you c

Post writing is also a fun, if you know then you can write if not it is complex
to write.

# Your style is very unique compared to other people I have read stuff from. Thanks for posting when you have the opportunity, Guess I will just book mark this web site. 2018/11/14 17:43 Your style is very unique compared to other people

Your style is very unique compared to other people I have read stuff from.
Thanks for posting when you have the opportunity, Guess I will just book mark this web site.

# This site certainly has all the information and facts I needed about this subject and didn't know who to ask. 2018/11/21 1:27 This site certainly has all the information and f

This site certainly has all the information and facts I needed about this subject and didn't know who to ask.

# wonderful put up, very informative. I'm wondering why the opposite experts of this sector do not understand this. You should continue your writing. I'm confident, you've a great readers' base already! 2019/04/05 4:15 wonderful put up, very informative. I'm wondering

wonderful put up, very informative. I'm wondering why the opposite experts
of this sector do not understand this. You should continue your writing.

I'm confident, you've a great readers' base already!

# Hi there, every time i used to check weblog posts here in the early hours in the dawn, as i enjoy to find out more and more. 2019/05/06 9:43 Hi there, every time i used to check weblog posts

Hi there, every time i used to check weblog posts here in the early hours in the dawn, as i
enjoy to find out more and more.

# Heya i'm for the primary time here. I found this board and I to find It truly helpful & it helped me out much. I'm hoping to give something again and aid others such as you aided me. 2019/05/31 17:29 Heya i'm for the primary time here. I found this b

Heya i'm for the primary time here. I found this board and I to find
It truly helpful & it helped me out much. I'm hoping to
give something again and aid others such as
you aided me.

# I was suggested this web site by my cousin. I'm not sure whether this post is written by him as no one else know such detailed about my problem. You are incredible! Thanks! 2019/09/05 17:39 I was suggested this web site by my cousin. I'm no

I was suggested this web site by my cousin. I'm not sure whether this post is written by him as no one else know
such detailed about my problem. You are incredible! Thanks!

# zpTZmHwYuysqKmHlDWB 2021/07/03 1:42 https://mega.nz/file/D0NHhSaR#dlb9ue4wJfEeUCZvEW8b

Really informative blog.Thanks Again. Great.

# Hello everyone, it's my first go to see at this website, and article is really fruitful for me, keep up posting these types of posts. 2022/03/25 5:09 Hello everyone, it's my first go to see at this we

Hello everyone, it's my first go to see at this
website, and article is really fruitful for me, keep up posting these types of posts.

# ロレックス 時計 自動巻き 2022/06/19 16:18 biquioobiq@nifty.com

売れ筋★高級レザー!男女の財布!ロレックス デイトナハイブランドの一流アイテムをお手頃価格でご提供。
送料無料★20気圧クロノグラフ搭載人気メンズ腕時計★
プレゼントに当店オススメなGAGA MILANO
GAGA MILANO 最安値に挑戦中!
温もり溢れるレザー財布がズラリ!福を呼び込む春財布
当店人気の海外ブランドが最安値挑戦価格!要チェック
水をはじくリバティボストン
軽量生地を使用した大容量ボストンバッグ
当店人気NO.1!女子に嬉しいたっぷり収納レザー長財布

# chloroquine tablets buy online 2022/12/26 23:31 MorrisReaks

chloroquine without a doctor prescription https://www.hydroxychloroquinex.com/

タイトル
名前
Url
コメント