Observerパターンは、GoFのデザインパターンの一つであり、オブジェクト間の依存関係を管理するために使われます。
このパターンでは、一つのオブジェクト(Subject)が状態の変化を通知し、それに応じて他のオブジェクト(Observer)がその変化に反応します。
本記事では、Observerパターンの概要と、Java、C++、C#での実装サンプルを紹介します。
Observerパターンとは
Observerパターンは、オブジェクト間の1対多の関係を簡単に管理するために設計されたデザインパターンです。
状態の変更を通知する側のオブジェクト(Subject)と、その変更を監視し反応する側のオブジェクト(Observer)が存在します。
Observerパターンを使うことで、状態変更が発生したときに、複数のオブジェクトが自動的に同期される仕組みを実現できます。
Observerパターンの特徴
Observerパターンは、以下の特徴を持っています。
Observerパターンの使い方
Observerパターンの典型的な使い方は、ユーザーインターフェースやイベントリスナーです。
例えば、ボタンがクリックされたときにそのイベントを複数のリスナーが受け取るという状況は、Observerパターンで簡単に管理できます。
Observerパターンのクラス構造
Observerパターンでは、通常次のようなクラス構造を持ちます。
Observerパターン実装サンプル
ここでは、Java、C++、C#それぞれでObserverパターンを実装した例を示します。
JavaでのObserverパターン実装
import java.util.ArrayList;
import java.util.List;
// Subjectクラス
class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
// Observerクラス
abstract class Observer {
protected Subject subject;
public abstract void update();
}
// ConcreteObserverクラス
class ConcreteObserver extends Observer {
public ConcreteObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("State changed to: " + subject.getState());
}
}
// 実行クラス
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new ConcreteObserver(subject);
System.out.println("State change: 10");
subject.setState(10);
System.out.println("State change: 20");
subject.setState(20);
}
}
C++でのObserverパターン実装
#include <iostream>
#include <vector>
class Observer;
// Subjectクラス
class Subject {
private:
std::vector<Observer*> observers;
int state;
public:
int getState() {
return state;
}
void setState(int state) {
this->state = state;
notifyAllObservers();
}
void attach(Observer* observer) {
observers.push_back(observer);
}
void notifyAllObservers();
};
// Observerクラス
class Observer {
protected:
Subject* subject;
public:
virtual void update() = 0;
};
// ConcreteObserverクラス
class ConcreteObserver : public Observer {
public:
ConcreteObserver(Subject* subject) {
this->subject = subject;
this->subject->attach(this);
}
void update() override {
std::cout << "State changed to: " << subject->getState() << std::endl;
}
};
void Subject::notifyAllObservers() {
for (Observer* observer : observers) {
observer->update();
}
}
// 実行クラス
int main() {
Subject subject;
ConcreteObserver observer(&subject);
std::cout << "State change: 10" << std::endl;
subject.setState(10);
std::cout << "State change: 20" << std::endl;
subject.setState(20);
return 0;
}
C#でのObserverパターン実装
using System;
using System.Collections.Generic;
// Subjectクラス
class Subject {
private List<Observer> observers = new List<Observer>();
private int state;
public int GetState() {
return state;
}
public void SetState(int state) {
this.state = state;
NotifyAllObservers();
}
public void Attach(Observer observer) {
observers.Add(observer);
}
public void NotifyAllObservers() {
foreach (Observer observer in observers) {
observer.Update();
}
}
}
// Observerクラス
abstract class Observer {
protected Subject subject;
public abstract void Update();
}
// ConcreteObserverクラス
class ConcreteObserver : Observer {
public ConcreteObserver(Subject subject) {
this.subject = subject;
this.subject.Attach(this);
}
public override void Update() {
Console.WriteLine("State changed to: " + subject.GetState());
}
}
// 実行クラス
class Program {
static void Main(string[] args) {
Subject subject = new Subject();
new ConcreteObserver(subject);
Console.WriteLine("State change: 10");
subject.SetState(10);
Console.WriteLine("State change: 20");
subject.SetState(20);
}
}
まとめ
Observerパターンは、オブジェクト間の依存関係を効率的に管理し、状態の変更を自動的に監視者に通知できるデザインパターンです。
このパターンを使うことで、アプリケーションの拡張性や柔軟性を向上させることができます。
今回の記事では、Observerパターンの基本的な使い方と実装サンプルをJava、C++、C#で紹介しました。
特に、ユーザーインターフェースやイベントリスナーなど、リアルタイムでの状態管理が必要な場面でObserverパターンは非常に有効です。