zoukankan      html  css  js  c++  java
  • 设计模式(行为模式)——观察者模式

    1 定义

    定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    2 适用性

    1)当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将二者封装在独立的对象中以使它们可以各自独立地改变和复用。

    2)当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时。

    3)当一个对象必须通知其他对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

    3 结构

    说明:

    1)Subject(目标):目标知道它的观察者。可以有任意多个观察者观察同一个目标。提供注册和删除观察者对象的接口。

    2)Observer(观察者):为那些在目标发生改变时需要获得通知的对象定义一个更新接口。

    3)ConcreteSubject(具体目标):将有关状态存入各ConcreteObserver对象。当它的状态发生改变时,向它的各个观察者发出通知。

    4)ConcreteObserver(具体观察者):维护一个指向ConcreteSubject对象的引用。存储有关状态,这些状态应与目标的状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。

    举例:

    1消息广播

    一个消息发布者,两个消息订阅者。发布者广播新的消息时,所有的订阅者都自动接收新的消息。

    目标(发布者)

    public interface ISubject
        {
            void SendMessage(string message);
        }
    

     目标的实现

    public class Subject : ISubject
    {
            public Action<string> PublishMessage;
    
            public void SendMessage(string message)
            {
                PublishMessage(message);
            }
    }
    

     观察者(订阅者)

    public interface IObserver
    {
            void GetNewMessage(string message);
    }
    public class Person1 : IObserver
    {
            public void GetNewMessage(string message)
            {
                Console.WriteLine("第一个人接收到新消息:" + message);
            }
    }
    public class Person2 : IObserver
    {
            public void GetNewMessage(string message)
            {
                Console.WriteLine("第二个人接收到新消息:" + message);
            }
    }
    

     连接目标与观察者

    static void Main(string[] args)
            {
                Person1 pf = new Person1();
                Person2 p2 = new Person2();
                Subject s = new Subject();
                s.PublishMessage += pf.GetNewMessage;
                s.PublishMessage += p2.GetNewMessage;
                while(true)
                {
       Console.WriteLine("广播消息:");
                    s.SendMessage(Console.ReadLine()); 
                }
            }
    

     运行结果:

    2 模拟温度调控器

    设置最高温与最低温,当输入温度大于最高温时,开始冷却器,关闭加热器;当输入温度小于最低温时,相反。

     

    目标(发布者)

    public interface ISubject
    {
            float CurrentTemperature { get; set; }
    }
    

     目标实现

    public class Subject:ISubject
    {
            private float _CT;
            public Action<float> PublishMessage;
            public float CurrentTemperature
            {
                get
                {
                    return _CT;
                }
                set
                {
                    if (this._CT != value)
                    {
                        PublishMessage(value);
                    }
                }
            }
    }
    

     观察者(订阅者)

    public interface IObserver
    {
            float Temperature { get; set; }
    
            void TemperatureChanged(float newTemperature);
    }
    

     加热器:

    public class Heater : IObserver
        {
            public float Temperature { set; get; }
            public Heater(float temperature)
            {
                Temperature = temperature;
                Console.WriteLine("温度最大值:" + temperature);
            }
            
    
            public void TemperatureChanged(float newTemperature)
            {
                if (newTemperature > Temperature)
                {
                    Console.WriteLine("加热器关闭");
                }
                else if (newTemperature == Temperature)
                {
                    Console.WriteLine("加热器关闭");
                }
                else
                {
                    Console.WriteLine("加热器开启");
                }
            }
        }
    

     制冷器:

    public class Cooler : IObserver
        {
            public Cooler(float temperature)
            {
                Temperature = temperature;
                Console.WriteLine("温度最小值:" + temperature);
            }
    
            public float Temperature{set;get;}
            public void TemperatureChanged(float newTemperature)
            {
                if (newTemperature > Temperature)
                {
                    Console.WriteLine("制冷器开启");
                }
                else if (newTemperature == Temperature)
                {
                    Console.WriteLine("制冷器关闭");
                }
                else
                {
                    Console.WriteLine("制冷器关闭");
                }
            }
        }
    

     连接目标与观察者

    static void Main(string[] args)
    {
                Heater h = new Heater(60);
                Cooler c = new Cooler(50);
                Pattern.Observer.Subject sub = new Pattern.Observer.Subject();
                sub.PublishMessage += h.TemperatureChanged;
                sub.PublishMessage += c.TemperatureChanged;
                while (true)
                {
                    Console.WriteLine("输入温度:");
                    string temp = Console.ReadLine();
                    sub.CurrentTemperature = float.Parse(temp);
                }
    }
    

     运行结果:

    3 观察者模式在Winform中的应用

    PM模式中,视图没有向控制器暴露出任何接口,那么控制器如何更新视图UI呢?一种比较简单的方式就是利用观察者模式。控制器相当于目标,视图层相当于观察者,当控制器接收到视图层数据后,更新模型,然后向所有观察者广播这一消息,视图层接收到消息后,完成更新UI的任务。代码示例见表现层设计模式那一章。

     

     

     

     

  • 相关阅读:
    bow lsa plsa
    拉普拉斯平滑处理 Laplace Smoothing
    程序员的出路在哪里
    Android各代码层获取系统时间的方法
    TCP/IP笔记 二.网络层(2)——ICMP,RIP,OSPF,BGP
    利用Xtrabackup备份集合恢复一台从库的过程
    char *和char[]的区别,困扰很长时间了,总结下
    不使用webview,用手机浏览器的android app
    [置顶] oracle 快速查询数据库各种信息、及转换对应java代码
    MySQL备份方案-->(利用mysqldump以及binlog二进制日志)
  • 原文地址:https://www.cnblogs.com/hdwgxz/p/8316342.html
Copyright © 2011-2022 走看看