Commandパターンは、GoF(Gang of Four)によって定義された23のデザインパターンの1つであり、操作のリクエストをオブジェクトとしてカプセル化する方法です。
このパターンにより、命令の発行者(クライアント)と実行者(レシーバー)を分離することができ、柔軟なシステム設計を可能にします。
この記事では、Commandパターンの概要、使用方法、そしてJava、C++、C#、VB.NETでの実装例について詳しく解説します。
Commandパターンとは
Commandパターンは、リクエストをオブジェクトとしてカプセル化し、リクエストを実行するオブジェクトをクライアントから分離するデザインパターンです。
このパターンを使用することで、コマンドの呼び出し、実行、取り消し、再実行を簡単に管理できます。
Commandパターンの利点
Commandパターンの主な利点は、コマンドの呼び出し元と実行者を分離できることです。これにより、以下のような利点が得られます:
- 操作の履歴管理が容易になる
- コマンドの取り消しや再実行が容易に行える
- クライアントとレシーバー間の依存関係を減らすことができる
Commandパターンの使い方
Commandパターンの使用方法は、主に3つの要素で構成されています。
コマンド、レシーバー、そしてインボーカーです。
コマンド
コマンドは、リクエストをカプセル化するオブジェクトで、実行される動作を表現します。
インターフェースで定義され、具体的なコマンドクラスでその実装が行われます。
レシーバー
レシーバーは、実際にリクエストに対して操作を実行するオブジェクトです。
具体的なコマンドクラスがレシーバーに対して操作を行います。
インボーカー
インボーカーは、コマンドを保持し、クライアントからの要求に基づいてコマンドを実行する役割を担います。
インボーカーはコマンドの詳細を知らずに、コマンドを実行できます。
Commandパターン実装サンプル
次に、CommandパターンをJava、C++、C#、VB.NETで実装したサンプルコードを紹介します。
JavaでのCommandパターン実装
interface Command {
void execute();
}
class Light {
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
public class CommandPatternExample {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
remote.setCommand(lightOff);
remote.pressButton();
}
}
C++でのCommandパターン実装
#include
using namespace std;
class Command {
public:
virtual void execute() = 0;
};
class Light {
public:
void turnOn() {
cout << "The light is on" << endl;
}
void turnOff() {
cout << "The light is off" << endl;
}
};
class LightOnCommand : public Command {
private:
Light* light;
public:
LightOnCommand(Light* light) : light(light) {}
void execute() {
light->turnOn();
}
};
class LightOffCommand : public Command {
private:
Light* light;
public:
LightOffCommand(Light* light) : light(light) {}
void execute() {
light->turnOff();
}
};
class RemoteControl {
private:
Command* command;
public:
void setCommand(Command* command) {
this->command = command;
}
void pressButton() {
command->execute();
}
};
int main() {
Light* light = new Light();
Command* lightOn = new LightOnCommand(light);
Command* lightOff = new LightOffCommand(light);
RemoteControl* remote = new RemoteControl();
remote->setCommand(lightOn);
remote->pressButton();
remote->setCommand(lightOff);
remote->pressButton();
delete light;
delete lightOn;
delete lightOff;
delete remote;
return 0;
}
C#でのCommandパターン実装
using System;
interface Command {
void Execute();
}
class Light {
public void TurnOn() {
Console.WriteLine("The light is on");
}
public void TurnOff() {
Console.WriteLine("The light is off");
}
}
class LightOnCommand : Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void Execute() {
light.TurnOn();
}
}
class LightOffCommand : Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void Execute() {
light.TurnOff();
}
}
class RemoteControl {
private Command command;
public void SetCommand(Command command) {
this.command = command;
}
public void PressButton() {
command.Execute();
}
}
class Program {
static void Main(string[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.SetCommand(lightOn);
remote.PressButton();
remote.SetCommand(lightOff);
remote.PressButton();
}
}
VB.NETでのCommandパターン実装
Interface Command
Sub Execute()
End Interface
Class Light
Public Sub TurnOn()
Console.WriteLine("The light is on")
End Sub
Public Sub TurnOff()
Console.WriteLine("The light is off")
End Sub
End Class
Class LightOnCommand
Implements Command
Private light As Light
Public Sub New(light As Light)
Me.light = light
End Sub
Public Sub Execute() Implements Command.Execute
light.TurnOn()
End Sub
End Class
Class LightOffCommand
Implements Command
Private light As Light
Public Sub New(light As Light)
Me.light = light
End Sub
Public Sub Execute() Implements Command.Execute
light.TurnOff()
End Sub
End Class
Class RemoteControl
Private command As Command
Public Sub SetCommand(command As Command)
Me.command = command
End Sub
Public Sub PressButton()
command.Execute()
End Sub
End Class
Module Program
Sub Main()
Dim light As New Light()
Dim lightOn As Command = New LightOnCommand(light)
Dim lightOff As Command = New LightOffCommand(light)
Dim remote As New RemoteControl()
remote.SetCommand(lightOn)
remote.PressButton()
remote.SetCommand(lightOff)
remote.PressButton()
End Sub
End Module
まとめ
Commandパターンは、操作のリクエストをオブジェクトとしてカプセル化し、クライアントとレシーバーを分離する強力なデザインパターンです。
これにより、命令の実行や取り消し、再実行の管理が容易になり、拡張性と柔軟性を高めることができます。
本記事では、Commandパターンの概要とその実装について、Java、C++、C#、VB.NETを使用した具体例を通じて解説しました。
ぜひ、自身のプロジェクトで活用してみてください。
