Observerパターンとは|GoFデザインパターンの解説

デザインパターンとは IT技術
IT技術

Observerパターンは、GoFのデザインパターンの一つであり、オブジェクト間の依存関係を管理するために使われます。

このパターンでは、一つのオブジェクト(Subject)が状態の変化を通知し、それに応じて他のオブジェクト(Observer)がその変化に反応します。

本記事では、Observerパターンの概要と、Java、C++、C#での実装サンプルを紹介します。

Observerパターンとは

Observerパターンは、オブジェクト間の1対多の関係を簡単に管理するために設計されたデザインパターンです。

状態の変更を通知する側のオブジェクト(Subject)と、その変更を監視し反応する側のオブジェクト(Observer)が存在します。

Observerパターンを使うことで、状態変更が発生したときに、複数のオブジェクトが自動的に同期される仕組みを実現できます。

Observerパターンの特徴

Observerパターンは、以下の特徴を持っています。

Point
  • 状態の変更を他のオブジェクトに効率的に通知できる
  • 監視対象(Subject)と監視者(Observer)の結合度が低い
  • 新しいObserverの追加が容易

Observerパターンの使い方

Observerパターンの典型的な使い方は、ユーザーインターフェースやイベントリスナーです。

例えば、ボタンがクリックされたときにそのイベントを複数のリスナーが受け取るという状況は、Observerパターンで簡単に管理できます。

Observerパターンのクラス構造

Observerパターンでは、通常次のようなクラス構造を持ちます。

Point
  1. Subject(被観察者):状態の変更を監視対象に通知する役割
  2. Observer(観察者):Subjectの状態が変化した際に、その変化に応じた処理を行う

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パターンは非常に有効です。

タイトルとURLをコピーしました