今日のトピックは「コマンドパターンとオブザーバーパターン」です。コマンドパターンとオブザーバーパターンは、オブジェクト間の相互作用を管理するためのデザインパターンです。コマンドパターンは、リクエストをオブジェクトとしてカプセル化し、リクエストの発行者と実行者を分離するために使用されます。一方、オブザーバーパターンは、あるオブジェクトの状態が変化したときに、関連するオブジェクトにその変化を通知するためのパターンです。
目次
基本概念の説明
コマンドパターン (Command Pattern)
コマンドパターンは、操作をオブジェクトとしてカプセル化し、そのオブジェクトを通じて操作を実行するパターンです。このパターンにより、リクエストの発行者と実行者を分離し、リクエストのキューイングやロギング、取り消しが可能になります。
オブザーバーパターン (Observer Pattern)
オブザーバーパターンは、オブジェクトの状態が変化した際に、それに依存するオブジェクト(オブザーバー)に通知を送る仕組みを提供するパターンです。これにより、オブジェクト間の依存関係を緩和し、動的なシステムの設計が容易になります。
各言語でのサンプルコード
Python
コマンドパターン
class Command:
def execute(self):
pass
class LightOnCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.on()
class LightOffCommand(Command):
def __init__(self, light):
self.light = light
def execute(self):
self.light.off()
class Light:
def on(self):
print("The light is on")
def off(self):
print("The light is off")
class RemoteControl:
def __init__(self):
self.commands = []
def set_command(self, command):
self.commands.append(command)
def execute_commands(self):
for command in self.commands:
command.execute()
# 使用例
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
remote = RemoteControl()
remote.set_command(light_on)
remote.set_command(light_off)
remote.execute_commands()
オブザーバーパターン
class Observer:
def update(self, message):
pass
class ConcreteObserver(Observer):
def update(self, message):
print(f"Observer received message: {message}")
class Subject:
def __init__(self):
self.observers = []
def add_observer(self, observer):
self.observers.append(observer)
def remove_observer(self, observer):
self.observers.remove(observer)
def notify_observers(self, message):
for observer in self.observers:
observer.update(message)
# 使用例
subject = Subject()
observer1 = ConcreteObserver()
observer2 = ConcreteObserver()
subject.add_observer(observer1)
subject.add_observer(observer2)
subject.notify_observers("Hello, Observers!")
C#
コマンドパターン
using System;
using System.Collections.Generic;
public interface ICommand {
void Execute();
}
public class Light {
public void On() {
Console.WriteLine("The light is on");
}
public void Off() {
Console.WriteLine("The light is off");
}
}
public class LightOnCommand : ICommand {
private Light _light;
public LightOnCommand(Light light) {
_light = light;
}
public void Execute() {
_light.On();
}
}
public class LightOffCommand : ICommand {
private Light _light;
public LightOffCommand(Light light) {
_light = light;
}
public void Execute() {
_light.Off();
}
}
public class RemoteControl {
private List<icommand> _commands = new List<icommand>();
public void SetCommand(ICommand command) {
_commands.Add(command);
}
public void ExecuteCommands() {
foreach (var command in _commands) {
command.Execute();
}
}
}
// 使用例
class Program {
static void Main() {
Light light = new Light();
ICommand lightOn = new LightOnCommand(light);
ICommand lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.SetCommand(lightOn);
remote.SetCommand(lightOff);
remote.ExecuteCommands();
}
}
</icommand></icommand>
オブザーバーパターン
using System;
using System.Collections.Generic;
public interface IObserver {
void Update(string message);
}
public class ConcreteObserver : IObserver {
public void Update(string message) {
Console.WriteLine($"Observer received message: {message}");
}
}
public class Subject {
private List<iobserver> _observers = new List<iobserver>();
public void AddObserver(IObserver observer) {
_observers.Add(observer);
}
public void RemoveObserver(IObserver observer) {
_observers.Remove(observer);
}
public void NotifyObservers(string message) {
foreach (var observer in _observers) {
observer.Update(message);
}
}
}
// 使用例
class Program {
static void Main() {
Subject subject = new Subject();
IObserver observer1 = new ConcreteObserver();
IObserver observer2 = new ConcreteObserver();
subject.AddObserver(observer1);
subject.AddObserver(observer2);
subject.NotifyObservers("Hello, Observers!");
}
}
</iobserver></iobserver>
C++
コマンドパターン
#include <iostream>
#include <vector>
class Command {
public:
virtual void execute() = 0;
virtual ~Command() {}
};
class Light {
public:
void on() {
std::cout << "The light is on" << std::endl;
}
void off() {
std::cout << "The light is off" << std::endl;
}
};
class LightOnCommand : public Command {
Light& light;
public:
LightOnCommand(Light& light) : light(light) {}
void execute() override {
light.on();
}
};
class LightOffCommand : public Command {
Light& light;
public:
LightOffCommand(Light& light) : light(light) {}
void execute() override {
light.off();
}
};
class RemoteControl {
std::vector<Command*> commands;
public:
void set_command(Command* command) {
commands.push_back(command);
}
void execute_commands() {
for (auto command : commands) {
command->execute();
}
}
};
// 使用例
int main() {
Light light;
LightOnCommand lightOn(light);
LightOffCommand lightOff(light);
RemoteControl remote;
remote.set_command(&lightOn);
remote.set_command(&lightOff);
remote.execute_commands();
return 0;
}
オブザーバーパターン
#include <iostream>
#include <vector>
#include <algorithm>
class Observer {
public:
virtual void update(const std::string& message) = 0;
virtual ~Observer() {}
};
class ConcreteObserver : public Observer {
public:
void update(const std::string& message) override {
std::cout << "Observer received message: " << message << std::endl;
}
};
class Subject {
std::vector<Observer*> observers;
public:
void add_observer(Observer* observer) {
observers.push_back(observer);
}
void remove_observer(Observer* observer) {
observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
}
void notify_observers(const std::string& message) {
for (auto observer : observers) {
observer->update(message);
}
}
};
// 使用例
int main() {
Subject subject;
ConcreteObserver observer1, observer2;
subject.add_observer(&observer1);
subject.add_observer(&observer2);
subject.notify_observers("Hello, Observers!");
return 0;
}
Java
コマンドパターン
interface Command {
void execute();
}
class Light {
public void on() {
System.out.println("The light is on");
}
public void off() {
System.out.println("The light is off");
}
}
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
}
class RemoteControl {
private List<command></command> commands = new ArrayList<>();
public void setCommand(Command command) {
commands.add(command);
}
public void executeCommands() {
for (Command command : commands) {
command.execute();
}
}
}
// 使用例
public class Main {
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.setCommand(lightOff);
remote.executeCommands();
}
}
オブザーバーパターン
interface Observer {
void update(String message);
}
class ConcreteObserver implements Observer {
public void update(String message) {
System.out.println("Observer received message: " + message);
}
}
class Subject {
private List<observer> observers = new ArrayList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
// 使用例
public class Main {
public static void main(String[] args) {
Subject subject = new Subject();
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
}
}
</observer>
JavaScript
コマンドパターン
class Command {
execute() {
throw new Error("This method should be overridden!");
}
}
class Light {
on() {
console.log("The light is on");
}
off() {
console.log("The light is off");
}
}
class LightOnCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.on();
}
}
class LightOffCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.off();
}
}
class RemoteControl {
constructor() {
this.commands = [];
}
setCommand(command) {
this.commands.push(command);
}
executeCommands() {
for (const command of this.commands) {
command.execute();
}
}
}
// 使用例
const light = new Light();
const lightOn = new LightOnCommand(light);
const lightOff = new LightOffCommand(light);
const remote = new RemoteControl();
remote.setCommand(lightOn);
remote.setCommand(lightOff);
remote.executeCommands();
オブザーバーパターン
class Observer {
update(message) {
throw new Error("This method should be overridden!");
}
}
class ConcreteObserver extends Observer {
update(message) {
console.log("Observer received message: " + message);
}
}
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notifyObservers(message) {
for (const observer of this.observers) {
observer.update(message);
}
}
}
// 使用例
const subject = new Subject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notifyObservers("Hello, Observers!");
各言語の解説
言語 | コマンドパターンの実装方法 | オブザーバーパターンの実装方法 | 特徴 |
---|---|---|---|
Python | クラスを使用して操作をカプセル化 | オブザーバーリストを使用して状態変化を通知 | シンプルで柔軟、直感的に実装可能 |
C# | インターフェースを使用して操作をカプセル化 | インターフェースとリストを使用して状態変化を通知 | 強力な型安全性と拡張性、オブジェクト指向の設計が容易 |
C++ | 仮想メソッドを使用して操作をカプセル化 | ポインタとリストを使用して状態変化を通知 | 高速で効率的、特に低レベルプログラムで有効 |
Java | インターフェースを使用して操作をカプセル化 | インターフェースとリストを使用して状態変化を通知 | 強力なオブジェクト指向機能と堅牢性、Javaの標準APIと統合が容易 |
JavaScript | クラスを使用して操作をカプセル化 | クラスと配列を使用して状態変化を通知 | 柔軟でシンプル、フロントエンドやNode.js環境に最適 |
まとめ
コマンドパターンは、操作をオブジェクトとしてカプセル化し、リクエストの発行者と実行者を分離することで、リクエストのキューイングやロギング、取り消しが可能になります。一方、オブザーバーパターンは、オブジェクトの状態が変化した際に関連するオブジェクトに通知を送る仕組みを提供し、システム内のオブジェクト間の依存関係を緩和します。次回は「チェーン・オブ・リスポンシビリティパターンとデコレータパターン」について学習しましょう。
コメント
コメント一覧 (1件)
[…] 3-2-2. コマンドパターンとオブザーバーパターン […]