まさるblog

越後在住アプリケーションエンジニア奮闘記

目次

Blog 利用状況

ニュース

07/04/23
新規加入しました。
よろしくお願いします。

07/06/02
東京勉強会#8に参加しました。

07/10/21
情報処理技術者試験(NW)受験しました。

07/11/17
オブジェクト指向分科会#2参加しました。

07/12/06
SOFTWARE TOYBOXオープンしました。

08/03/02
息子誕生しました。

08/03/05
twitterはじめました。

現在
子育て奮闘中です。
デザインパターン勉強中です。
iKnow!、ESLPodcastなどで英語勉強中です。

ブログパーツ

あわせて読みたい

書庫

日記カテゴリ

コミュニティ

色々

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

さて、前回のエントリでは、コメントにてεπιστημηさんととっちゃんさんに、『「イベント」はObserverパターンそのまんまやんけ』とツッコミをいただいたわけですが、今回は前回のコードを「イベント」を使って書き直してみます。

では、さっそく例を。

  1. イベント引数を定義する。 メンバとしてfrom, to, subjectを持ち、それぞれの読み取り専用プロパティを定義する。
    C# Code
    // NewMailイベント引数クラス
    class NewMailEventArgs : EventArgs
    {
        private readonly string from;
        private readonly string to;
        private readonly string subject;
    
        // コンストラクタ
        public NewMailEventArgs(string from, string to, string subject)
        {
            this.from = from;
            this.to = to;
            this.subject = subject;
        }
    
        public string From
        {
            get { return this.from; }
        }
    
        public string To
        {
            get { return this.to; }
        }
    
        public string Subject
        {
            get { return this.subject; }
        }
    }
    
  2. SubjectであるMailManagerクラスを定義する。 内部にはイベントNewMailを持ち、通知メソッドはデリゲートによるメソッド呼び出しを行う。
    C# Code
    // メール管理クラス
    class MailManager
    {
        // イベント定義
        public event EventHandler<NewMailEventArgs> NewMail;
    
        // 通知
        private void Notify(NewMailEventArgs e)
        {
            // デリゲートでメソッド呼び出し
            NewMail(this, e);
        }
    
        // データ設定
        public void SetData(string from, string to, string subject)
        {
            // NewMailEventArgs生成
            NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
    
            // 通知
            Notify(e);
        }
    }
    
  3. ObserverであるFaxクラス、Printerクラスを定義する。 それぞれ、通知を受けたときの動作を記述します。
    C# Code
    // Faxクラス
    class Fax
    {
        // 通知
        public void Notify(object sender, NewMailEventArgs e)
        {
            Console.WriteLine("Faxを送信します。");
            Console.WriteLine("From:{0}, To:{1}, Subject:{2}", e.From, e.To, e.Subject);
        }
    }
    // Printerクラス
    class Printer
    {
        // 通知
        public void Notify(object sender, NewMailEventArgs e)
        {
            Console.WriteLine("印刷します。");
            Console.WriteLine("From={0}, To={1}, Subject={2}", e.From, e.To, e.Subject);
        }
    }
    

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

 

実行用コード

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

        // Faxを登録
        Fax fax = new Fax();
        mm.NewMail += fax.Notify;

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

        // Printerを登録
        Printer printer = new Printer();
        mm.NewMail += printer.Notify;

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

        // Faxを削除
        mm.NewMail -= fax.Notify; 

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

実行結果

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

前回と同じ結果が得られました。

 

さて、前回のコードと比べて、今回のコードの違いは何でしょうか。思いつくところでは、

  1. インターフェースの定義が不要になった。
  2. 専用のEventArgsの定義が必要になった。
  3. SubjectにObserverを登録、削除するためのメソッド定義が不要になった。
  4. SubjectにObserverのコレクションが不要になり、代わりにイベントメンバが必要になった。
  5. Subjectに登録するのがObserver自体ではなく、Observerのメソッドになった。

といったところでしょうか。

上記内容より、前回に比べた利点を簡単にまとめると以下のようになります。

「イベント」を使うことによりコーディング量を削減でき、また共通のインターフェースを実装していなくとも、シグネチャが一致すればどんなクラスにも通知が可能。

 

というわけで、C#,VB.NETでObserverパターンが必要になったら、「イベント」を積極的に使う方向でいこうと思います。使わないほうがいいようなときがあったらツッコミをお願いします。

 

#こんな感じで「ないす」なところが説明出来ているでしょうか?>επιστημηさん

 

※今回扱ったイベント周りは、「プログラミング .NET Framework 第2版」の「第10章 イベント」にて詳しく解説されています。

投稿日時 : 2007年5月25日 22:32

Feedback

# re: デザインパターンを学ぶ~その5:Ovserverパターン(2)~ 2007/05/25 22:46 えムナウ

.NET Framework では、オブザーバの役割を実現するためにデリゲートおよびイベントの概念が定義されています。

目的がそうなんですから、『「イベント」はObserverパターンそのまんまやんけ』はその通りなんです。

このマイクロソフトのページを読んでください。
http://www.microsoft.com/japan/msdn/practices/type/Patterns/enterprise/desobserver.aspx

オブザーバをイベントで実装するあたりも書いてあります。
http://www.microsoft.com/japan/msdn/practices/type/Patterns/enterprise/impobserverinnet.aspx

# re: デザインパターンを学ぶ~その5:Ovserverパターン(2)~ 2007/05/25 23:07 ひろえむ

ただ、イベントがオブザーバーのためだけにあるんじゃないところも注意が必要ですね(^^;

なので、オブザーバーとして表現する場合とそうじゃない場合のコーディングや命名に注意する必要があるんですけどね(^^;

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

>えムナウさん
紹介していただいたページは未チェックでした。有益な情報ありがとうございます。勉強させていただきます。

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

>ひろえむさん
>ただ、イベントがオブザーバーのためだけにあるんじゃないところも注意が必要ですね(^^;
いつだったかεπιστημηさんとこでやってた、イベント連鎖で再起呼び出しみたいなことですかね?
普段イベントなんて「ボタンクリック時の処理を書く」とかにしか使ってないので、
いまいちイメージが湧きませんorz

具体的にはどんな感じで使ってるんでしょうか?

# re: デザインパターンを学ぶ~その5:Ovserverパターン(2)~ 2007/05/27 17:07 かずくん

Observerパターンは、
「見て!見て!僕こんなに変わったんだよ!」
とオブジェクトの変更を通知する用途が基本かなと思います。
つまり、Controller→View方向ということ。

オブザーバーとして表現しない場合とは、
「オラ、オラ、オラァァァァァァァァァァァァ!!!、
項目入力して、ボタン押されたから、内部の状態変更しろやぁぁぁぁぁぁぁぁぁぁぁ!!!」
と、あまりオブジェクトというものを意識しない、
低レベルイベントや関数のコールのようなことを言っているのかな?と思いました。
方向としては、View→Controller

ホントのところは、ひろえむさんの回答wktk

# re: デザインパターンを学ぶ~その5:Ovserverパターン(2)~ 2007/05/31 9:50 シャノン

イベントとデリゲートの使い分けとか考えるとハマるかもー?

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

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

タイトル  
名前  
Url
コメント