まさるblog

越後在住子持ちプログラマー奮闘記 - Author:まさる(高野 将、TAKANO Sho)

目次

Blog 利用状況

ニュース

著書

2010/7発売


Web掲載記事

@IT

.NET開発を始めるVB6プログラマーが知るべき9のこと

CodeZine

実例で学ぶASP.NET Webフォーム業務アプリケーション開発のポイント

第1回 3層データバインドを正しく活用しよう(前編)

ブログパーツ


書庫

日記カテゴリ

コミュニティ

デザインパターンを学ぶ~その4:Ovserverパターン(1)~

Observer (オブザーバー)
 観察者、監視者、etc...

Observerパターンとは、あるオブジェクトの状態の変化を、他のオブジェクトに通知するためのパターンです。状態を通知する側をSubject(被検者)、通知を受ける側をObserver(監視者)とみなして、SubjectにObserverを登録し、登録されたObserverすべてに対して変更を通知します。

 

以下に例を示します。

  1. Observerのインターフェースを定義する。 通知を受け取るためのメソッドを定義します。
    C# Code
    // Observerインターフェース
    public interface IObserver
    {
        // 通知
        void Notify(string from, string to, string subject);
    }
    
  2. Subjectのインターフェースを定義する。 Observerの登録、Observerの登録解除、Observerへの通知を行うメソッドを定義します。
    C# Code
    // Subjectインターフェース
    public interface ISubject
    {
        // Observer登録
        void RegisterObserver(IObserver observer);
    
        // Observer削除
        void RemoveObserver(IObserver observer);
    
        // Observerへ通知
        void NotifyObserver();
    }
    
  3. ISubjectインターフェースを実装したMailManagerクラスを定義する。内部にIObjectクラスのコレクションを保持し、RegisterObserverでAdd、RemoveObserverでRemoveを行う。そして、NotifyObserverではIObjectのコレクションすべてに対して、Notifyメソッドの呼び出しを行う。
    C# Code
    // メール管理クラス
    public class MailManager : ISubject
    {
        // Observerリスト
        private List<IObserver> observers;
    
        // privateメンバ
        private string from;
        private string to;
        private string subject;
    
        // コンストラクタ
        public MailManager()
        {
            observers = new List<IObserver>();
        }
    
        // Observer登録
        public void RegisterObserver(IObserver observer)
        {
            observers.Add(observer);
        }
    
        // Observer削除
        public void RemoveObserver(IObserver observer)
        {
            observers.Remove(observer);
        }
    
        // Observerへ通知
        public void NotifyObserver()
        {
            foreach ( IObserver observer in observers )
            {
                observer.Notify(from, to, subject);
            }
        }
    
        // データ設定
        public void SetData(string from, string to, string subject)
        {
            // プライベートメンバに設定
            this.from = from;
            this.to = to;
            this.subject = subject;
    
            // Observerに通知
            NotifyObserver();
        }
    }
    
  4. IObserverインターフェースを実装したFaxクラス、Printerクラスを定義する。 それぞれ、通知を受けたときの動作を記述します。
    C# Code
    // Faxクラス
    public class Fax : IObserver
    {
        // 通知
        public void Notify(string from, string to, string subject)
        {
            Console.WriteLine("Faxを送信します。");
            Console.WriteLine("From:{0}, To:{1}, Subject:{2}", from, to, subject);
        }
    }
    
    // Printerクラス
    public class Printer : IObserver
    {
        // 通知
        public void Notify(string from, string to, string subject)
        {
            Console.WriteLine("印刷します。");
            Console.WriteLine("From={0}, To={1}, Subject={2}", from, to, subject);
        }
    }
    

以上のコードを実行してみます。

 

実行用コード

C# Code
class ObserverTest
{
    static void Main(string[] args)
    {
        // MailManagerインスタンス生成
        MailManager mm = new MailManager();

        // Faxを登録
        Fax fax = new Fax();
        mm.RegisterObserver(fax);

        // データ設定、通知
        Console.WriteLine("1回目");
        mm.SetData("わんくま同盟", "まさる", "勉強会の連絡");

        // Printerを登録
        Printer printer = new Printer();
        mm.RegisterObserver(printer);

        // データ設定、通知
        Console.WriteLine("2回目");
        mm.SetData("わんくま同盟", "まさる", "補足");

        // Faxを削除
        mm.RemoveObserver(fax);

        // データ設定、通知
        Console.WriteLine("3回目");
        mm.SetData("わんくま同盟", "まさる", "訂正");
    }
}

実行結果

1回目
Faxを送信します。
From:わんくま同盟, To:まさる, Subject:勉強会の連絡
2回目
Faxを送信します。
From:わんくま同盟, To:まさる, Subject:補足
印刷します。
From=わんくま同盟, To=まさる, Subject=補足
3回目
印刷します。
From=わんくま同盟, To=まさる, Subject=訂正

上記のように、登録されたObserverにSubjectの変更が通知され、処理されているのが確認できます。また、Observerの登録解除が正しく行われているのも確認できます。

 

ところで、Observerパターンの動作ですが、あるオブジェクトから通知を受ける「モノ」の登録、削除を行い、登録された「モノ」すべてに対して通知を行うというところが、なんとなく「イベント」に似てますね。

次回はその辺をちょっと掘り下げてみようと思います。

投稿日時 : 2007年5月23日 0:09

Feedback

# re: デザインパターンを学ぶ~その4:Ovserverパターン(1)~ 2007/05/23 10:31 επιστημη

ちゅーか、「イベント」ってばまさしくObserverパターンのないすな実現形態だわ。

# re: デザインパターンを学ぶ~その4:Ovserverパターン(1)~ 2007/05/23 12:06 とっちゃん

「イベント」そのものかと...と書こうと思ったらすでに書かれてたw

自分でインターフェースまで規定するか、出来合いのものを使うかという「差」ですね。

# re: デザインパターンを学ぶ~その4:Ovserverパターン(1)~ 2007/05/23 12:47 まさる

>επιστημηさん、とっちゃんさん
たしかに、考えてみりゃ「イベント」の概念はまさにObserverパターンですね。ただその実装方法が違うだけと。

帰ったら「イベント」の中身を調べてみて、どう違うか、どの辺が「ないす」(by επιστημηさん)か考えてみようと思います。

# デザインパターンを学ぶ~その5:Ovserverパターン(2)~ 2007/05/25 22:32 まさるblog

デザインパターンを学ぶ~その5:Ovserverパターン(2)~

# デザインパターンを学ぶ~その10:ちょっとだけObserverパターン~ 2007/08/02 21:36 まさるblog

デザインパターンを学ぶ~その10:ちょっとだけObserverパターン~

# デザインパターンを学ぶ~その27:IObservable、IObserverでObserverパターン~ 2011/08/23 23:35 まさるblog

デザインパターンを学ぶ~その27:IObservable、IObserverでObserverパターン~

# 激安ブランドのオーデマピゲ腕時計 2021/11/14 2:58 ydjibpsca@yahoo.co.jp

激安ブランド直営店
1.最も合理的な価格で商品を消費者に提供致します。
2.弊社の商品品数大目で、商品は安めです!商品現物写真。
3.数量制限無し、一個の注文も、OKです。
4.1個も1万個も問わず、誠心誠意対応します。
5.不良品の場合、弊社が無償で交換します。不明点、疑問点等があれば、ご遠慮なく言って下さい。
以上よろしくお願いいたします
休業日: 365天受付年中無休

タイトル
名前
Url
コメント