zoukankan      html  css  js  c++  java
  • Observer设计模式

    Observer设计模式是针对:一个对象对多个对象中,一个对象发生状态改变,其他附属对象发生相应的更新。是一种松耦合的设计模式。

    例子:

    假设我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:1、扬声器会开始发出语音,告诉你水的温度;2、液晶屏也会改变水温的显示,来提示水已经快烧开了。

    现在我们需要写个程序来模拟这个烧水的过程,我们将定义一个类来代表热水器,我们管它叫:Heater,它有代表水温的字段,叫做temperature;当然,还有必不可少的给水加热方法BoilWater(),一个发出语音警报的方法MakeAlert(),一个显示水温的方法,ShowMsg()。

    namespace Delegate {
        class Heater {
        private int temperature; // 水温
        // 烧水
        public void BoilWater() {
            for (int i = 0; i <= 100; i++) {
               temperature = i;
    
               if (temperature > 95) {
                   MakeAlert(temperature);
                   ShowMsg(temperature);
                }
            }
        }
    
        // 发出语音警报
        private void MakeAlert(int param) {
           Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);
        }
        
        // 显示水温
        private void ShowMsg(int param) {
           Console.WriteLine("Display:水快开了,当前温度:{0}度。" , param);
        }
    }
    
    class Program {
        static void Main() {
           Heater ht = new Heater();
           ht.BoilWater();
        }
    }
    }

    上面的例子显然能完成我们之前描述的工作,但是却并不够好。现在假设热水器由三部分组成:热水器、警报器、显示器,它们来自于不同厂商并进行了组装。那么,应该是热水器仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由警报器发出警报、显示器显示提示和水温。

    这时候,上面的例子就应该变成这个样子:   

     1 // 热水器
     2 public class Heater { 
     3     private int temperature;
     4         
     5     // 烧水
     6     private void BoilWater() {
     7        for (int i = 0; i <= 100; i++) {
     8            temperature = i;
     9         }
    10     }
    11 }
    12 
    13 // 警报器
    14 public class Alarm{
    15     private void MakeAlert(int param) {
    16        Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:" , param);
    17     }
    18 }
    19 
    20 // 显示器
    21 public class Display{
    22     private void ShowMsg(int param) {
    23        Console.WriteLine("Display:水已烧开,当前温度:{0}度。" , param);
    24     }
    25 }

    这里就出现了一个问题:如何在水烧开的时候通知报警器和显示器?在继续进行之前,我们先了解一下Observer设计模式,Observer设计模式中主要包括如下两类对象:

    1. Subject:监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个监视对象,它包含的其他对象所感兴趣的内容,就是temprature字段,当这个字段的值快到100时,会不断把数据发给监视它的对象。
    2. Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。

    在本例中,事情发生的顺序应该是这样的:

    1. 警报器和显示器告诉热水器,它对它的温度比较感兴趣(注册)。
    2. 热水器知道后保留对警报器和显示器的引用。
    3. 热水器进行烧水这一动作,当水温超过95度时,通过对警报器和显示器的引用,自动调用警报器的MakeAlert()方法、显示器的ShowMsg()方法。
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using System.Threading;
     6 
     7 namespace Delegate_Event
     8 {
     9     class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             Alarm a = new Alarm();
    14             Display d=new Display();
    15 
    16             Heater h = new Heater();
    17 
    18             h.makeBoilDelegateEvent += a.MakeAlert;
    19             h.makeBoilDelegateEvent += d.showMsg;
    20             h.OnmakeBoilDelegate("123");
    21             Console.ReadKey();
    22         }
    23     }
    24 
    25     
    26     //热水器
    27     public class Heater
    28     {
    29         public delegate void BoilDelegate(int name);
    30         public event BoilDelegate makeBoilDelegateEvent;
    31 
    32         public void OnmakeBoilDelegate(string name)
    33         {
    34             for (int i = 0; i < 1000; i++)
    35             {
    36                 Thread.Sleep(2000);
    37 
    38                 if (makeBoilDelegateEvent != null)
    39                 {
    40                     makeBoilDelegateEvent(i);
    41                 }
    42             }
    43             
    44         }
    45     }
    46 
    47     //报警器
    48     public class Alarm
    49     {
    50         //报警器有个报警的动作
    51         public void MakeAlert(int c)
    52         {
    53             if (c >= 100)
    54             {
    55                 Console.WriteLine("Alarm:咕咕咕......咕咕咕......咕咕咕......,水烧开了!");
    56             }
    57         }
    58     }
    59 
    60     //显示器
    61     public class Display
    62     {
    63         //显示温度
    64         public void showMsg(int c)
    65         {
    66             Console.WriteLine("Display:现在温度"+c+"摄氏度!");
    67         }
    68     }
    69 }
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 
     5 namespace Delegate {
     6     // 热水器
     7     public class Heater {
     8        private int temperature;
     9        public string type = "RealFire 001";       // 添加型号作为演示
    10        public string area = "China Xian";         // 添加产地作为演示
    11        //声明委托
    12        public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);
    13        public event BoiledEventHandler Boiled; //声明事件
    14 
    15        // 定义BoiledEventArgs类,传递给Observer所感兴趣的信息
    16        public class BoiledEventArgs : EventArgs {
    17            public readonly int temperature;
    18            public BoiledEventArgs(int temperature) {
    19               this.temperature = temperature;
    20            }
    21        }
    22 
    23        // 可以供继承自 Heater 的类重写,以便继承类拒绝其他对象对它的监视
    24        protected virtual void OnBoiled(BoiledEventArgs e) {
    25            if (Boiled != null) { // 如果有对象注册
    26               Boiled(this, e);  // 调用所有注册对象的方法
    27            }
    28        }
    29        
    30        // 烧水。
    31        public void BoilWater() {
    32            for (int i = 0; i <= 100; i++) {
    33               temperature = i;
    34               if (temperature > 95) {
    35                   //建立BoiledEventArgs 对象。
    36                   BoiledEventArgs e = new BoiledEventArgs(temperature);
    37                   OnBoiled(e);  // 调用 OnBolied方法
    38               }
    39            }
    40        }
    41     }
    42 
    43     // 警报器
    44     public class Alarm {
    45        public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {
    46            Heater heater = (Heater)sender;     //这里是不是很熟悉呢?
    47            //访问 sender 中的公共字段
    48            Console.WriteLine("Alarm:{0} - {1}: ", heater.area, heater.type);
    49            Console.WriteLine("Alarm: 嘀嘀嘀,水已经 {0} 度了:", e.temperature);
    50            Console.WriteLine();
    51        }
    52     }
    53 
    54     // 显示器
    55     public class Display {
    56        public static void ShowMsg(Object sender, Heater.BoiledEventArgs e) {   //静态方法
    57            Heater heater = (Heater)sender;
    58            Console.WriteLine("Display:{0} - {1}: ", heater.area, heater.type);
    59            Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", e.temperature);
    60            Console.WriteLine();
    61        }
    62     }
    63 
    64     class Program {
    65        static void Main() {
    66            Heater heater = new Heater();
    67            Alarm alarm = new Alarm();
    68 
    69            heater.Boiled += alarm.MakeAlert;   //注册方法
    70            heater.Boiled += (new Alarm()).MakeAlert;      //给匿名对象注册方法
    71            heater.Boiled += new Heater.BoiledEventHandler(alarm.MakeAlert);    //也可以这么注册
    72            heater.Boiled += Display.ShowMsg;       //注册静态方法
    73 
    74            heater.BoilWater();   //烧水,会自动调用注册过对象的方法
    75        }
    76     }
    77 }
    78 
    79 输出为:
    80 Alarm:China Xian - RealFire 001:
    81 Alarm: 嘀嘀嘀,水已经 96 度了:
    82 Alarm:China Xian - RealFire 001:
    83 Alarm: 嘀嘀嘀,水已经 96 度了:
    84 Alarm:China Xian - RealFire 001:
    85 Alarm: 嘀嘀嘀,水已经 96 度了:
    86 Display:China Xian - RealFire 001:
    87 Display:水快烧开了,当前温度:96度。
    88 // 省略 ...

    原文地址:http://www.cnblogs.com/jimmyzhang/archive/2007/09/23/903360.html

  • 相关阅读:
    Java实现 计蒜客 拯救行动
    Java实现 计蒜客 拯救行动
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 174 地下城游戏
    Java实现 LeetCode 173 二叉搜索树迭代器
    Java实现 LeetCode 173 二叉搜索树迭代器
    Visual Studio的SDK配置
    怎样使用CMenu类
    mfc menu用法一
  • 原文地址:https://www.cnblogs.com/manyiString/p/2516911.html
Copyright © 2011-2022 走看看