nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

Observerパターン [C#] [push型]

Observerパターンとは

あるオブジェクトの状態に依存するオブジェクトがあるとき、状態の変化をそれらのオブジェクトに依存せずに自動的に通知するパターン

push型とpull型

Observerパターンでは,push型とpull型があります。違いは以下のとおり。

  • push型 : updateの引数に変更された状態を渡すことで、Observerに通知する
  • pull型 : updateを呼び出されたタイミングでObserverがObservableに状態を問い合わせる

本記事では、push型のObserverパターンについて説明します。

Observerパターンのpush型のクラス図

f:id:nprogram:20190731224438p:plain

各クラスの役割

  • Subject
    • Observer の登録と削除、状態変化の通知の機能を定義する
  • Observer
    • Subject から通知を受け取る機能を定義する
    • ConcreteSubject‐ConcreteObserver 間の結合を抽象的に(直接的な依存関係を排除)するためのインターフェース
  • ConcreteSubject
    • Observer に状態の変化を通知する。
    • Observer とは一対多の関係。
    • 状態の変化を登録されているすべてのObserverに通知する責務を持つ
    • 複数の異なる ConcreteObserverに対応できるように、抽象的に Observer のリストを保持する
    • 被観察者
    • 別名として観察可能な(Observable)クラスとも呼ばれる
    • ConcreteSubjectはConcreteObserverの存在を知らない。Observerの存在は知っている
  • ConcreteObserver
    • Subject の状態が変化されたことが通知される
    • 状態変化による無矛盾性を保つ
    • 観察者

コード

using System;
using System.Collections.Generic;

namespace Observer_Pattern
{
    class Program
    {
        static void Main(string[] args)
        {
            ConcreteObserver observer1 = new ConcreteObserver();
            ConcreteObserver observer2 = new ConcreteObserver();

            ConcreteSubject subject = new ConcreteSubject();

            subject.Add(observer1);
            subject.Add(observer2);

            Random rnd = new System.Random();

            for (int i = 0; i < 3; i++)
            {
                // Set Random Value from 0 to 9
                subject.Status = rnd.Next(10);
            }
        }
    }

    interface IObserver
    {
        void Update(int num);
    }

    interface ISubject
    {
        void Add(IObserver item);
        void Delete(IObserver item);
        void Notify();
    }

    class ConcreteObserver : IObserver
    {
        public void Update(int num)
        {
            Console.WriteLine("Update Value: {0}", num);
        }
    }

    class ConcreteSubject : ISubject
    {
        private List<IObserver> _observers = new List<IObserver>();

        public void Add(IObserver item)
        {
            _observers.Add(item);
        }

        public void Delete(IObserver item)
        {
            _observers.Remove(item);
        }

        public void Notify()
        {
            _observers.ForEach(observer => observer.Update(_Status));

            //foreach (var item in _observers)
            //{
            //    item.Update(_Status);
            //}
        }

        private int _Status;
        public int Status
        {
            get { return _Status; }
            set
            {
                _Status = value;
                Notify();
            }
        }
    }
}
Update Value: 4
Update Value: 4
Update Value: 2
Update Value: 2
Update Value: 5
Update Value: 5

参考リンク