nprogram’s blog

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

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

Observerパターンとは

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

push型とpull型

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

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

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

参考

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

f:id:nprogram:20190801081705p:plain

コード

using System;
using System.Collections.Generic;

namespace Observer_Pattern_push_type
{
    class Program
    {
        static void Main(string[] args)
        {
            Person model = new Person();
            View view = new View();
            view.DataSource = model;    // データバインド

            model.Id = 123;
            model.Name = "Ichiro";
        }
    }

    interface IObserver
    {
        void Update(Observable observer);
    }

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

    /// <summary>
    /// テキスト表示用のUI部品 (ダミー)
    /// </summary>
    class TextControl
    {
        public string Text
        {
            set { Console.WriteLine("TextControl is updated: {0}", value); }
        }
    }

    /// <summary>
    /// 監視するクラス
    /// </summary>
    class View : IObserver
    {
        TextControl nameText = new TextControl();
        TextControl idText = new TextControl();

        public void Update(Observable item)
        {
            var person = item as Person;

            if (person != null)
            {
                nameText.Text = person.Id.ToString();
                idText.Text = person.Name;
            }
        }

        public Person DataSource
        {
            set { value.Add(this); }
        }
    }

    /// <summary>
    /// 監視されるクラス
    /// </summary>
    abstract class Observable : 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(this));
        }

        protected void Update() // 更新イベント
        {
            Notify();
        }
    }

    /// <summary>
    /// Modelクラス
    /// </summary>
    class Person : Observable
    {
        private int _Id;
        public int Id
        {
            get { return _Id; }
            set
            {
                if (value != _Id)
                {
                    _Id = value;
                    Update();
                }
            }
        }

        private string _Name;
        public string Name
        {
            get { return _Name; }
            set
            {
                if (value != _Name)
                {
                    _Name = value;
                    Update();
                }
            }
        }
    }
}
TextControl is updated: 123
TextControl is updated:
TextControl is updated: 123
TextControl is updated: Ichiro