观察者模式(Observer Pattern)

原创 2012年03月21日 23:05:44

观察者模式(Observer Pattern):
定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,
会通知所有观察者对象,使它们能够自动更新自己。

Subject类:被观察对象
(1)它把所有对观察者的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,
可以增加和删除观测者对象。
ConcreteSubject类:具体的被观察对象
(1)将有关状态存入具体的观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知
Observer类:抽象观察者
(1)为所有具体观察者定义一个接口,在得到主题的通知时更新自己
ConcreteObserver:具体观察者
(1)实现抽象观察者角色所要求的更新接口,以便本身的状态与主题的状态想协调。

/// <summary>
    /// Suject类,可译为主题或抽象通知者、被观察对象,一般用一个抽象类或一个接口实现。
    /// </summary>
    public abstract class Subject
    {
        private IList<Observer> observers = new List<Observer>();

        /// <summary>
        /// 增加观察者
        /// </summary>
        /// <param name="observer"></param>
        public void Attach(Observer observer)
        {
            observers.Add(observer);
        }

        /// <summary>
        /// 移除观察者
        /// </summary>
        /// <param name="observer"></param>
        public void Detach(Observer observer)
        {
            if (observers.Contains(observer))
            {
                observers.Remove(observer);
            }
        }
        /// <summary>
        /// 通知观察者,更新所有的观察者
        /// </summary>
        public void Notify()
        {
            foreach (Observer observer in observers)
            {
                observer.Update();
            }
        }
    }

    /// <summary>
    /// ConcreteSubject类,具体的通知者,将有关状态存入具体观察者对象;在具体主题的内部
    /// 改变时,给所有登记过的观察者发出通知。
    /// </summary>
    public class ConcreteSubject:Subject
    {
        private string subjectState;

        public string SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }
    }

    /// <summary>
    /// Observer类,抽象观察者。一般用一个抽象类或接口实现。更新接口通常包含一个Update()的方法,
    /// 这个方法叫更新方法
    /// </summary>
    public abstract class Observer
    {
        public abstract void Update();
    }

    /// <summary>
    /// ConcreteObserver类,具体观察者,实现抽象观察者所提供的更新接口,以便使本身的状态与
    /// 通知者的状态向协调。具体观察者可以保存一个指向具体通知者对象的引用。
    /// </summary>
    public class ConcreteObserver : Observer
    {
        private string name;
        private string observerState;
        private ConcreteSubject subject;

        public ConcreteSubject Subject
        {
            get { return subject; }
            set { subject = value; }
        }

        public ConcreteObserver(ConcreteSubject subject, string name)
        {
            this.subject = subject;
            this.name = name;
        }

        public override void Update()
        {
            observerState = subject.SubjectState;
            Console.WriteLine("观察者{0}的状态是{1}",name,observerState);
        }

    }

 //客户端调用
    class Program
    {
        static void Main()
        {
            ConcreteSubject s = new ConcreteSubject();

            s.Attach(new ConcreteObserver(s, "X"));
            s.Attach(new ConcreteObserver(s, "Y"));

            s.SubjectState = "ABC";
            s.Notify();
        }
    }

实例:ATM取款
取款后,以邮件和短信方式通知取款人。

 

/// <summary>
    /// Observer类:抽象观察者,定义更新方法
    /// 依赖抽象观察者
    /// </summary>
    public interface IObserverAccount
    {
        void Update(Subject sueject);
    }

 

/// <summary>
    /// Subject类:抽象通知者类
    /// 依赖于抽象观察者,与具体的观察者无关
    /// </summary>
    public abstract class Subject
    {
        private IList<IObserverAccount> observers = new List<IObserverAccount>();

        private double _money;

        public double Money
        {
            get { return _money; }
            set { _money = value; }
        }

        public Subject(double money)
        {
            this._money = money;
        }

        public void AddObserver(IObserverAccount observer)
        {
            this.observers.Add(observer);
        }

        public void RemoveObserver(IObserverAccount observer)
        {
            if (observers.Contains(observer))
            {
                observers.Remove(observer);
            }

        }

        public void WithDraw()
        {
            foreach (IObserverAccount observer in observers)
            {
                observer.Update(this);
            }
        }
    }

 

/// <summary>
    /// 具体的通知者
    /// </summary>
    public class BankAccount:Subject
    {
        public BankAccount(double money)
            : base(money)
        {

        }
    }

 

/// <summary>
    /// 具体的观察者类
    /// </summary>
    public class Emailer:IObserverAccount
    {
        private string _emailer;

        public Emailer(string emailer)
        {
            this._emailer = emailer;
        }

        #region IObserverAccount 成员

        public void Update(Subject sueject)
        {
            Console.WriteLine("您于{0}在ATM机取款{1:C}",DateTime.Now,sueject.Money);
        }

        #endregion
    }

 

/// <summary>
    /// 具体观察者类
    /// </summary>
    public class Mobile:IObserverAccount
    {
        private string _phoneNumber;

        public Mobile(string phoneNumber)
        {
            this._phoneNumber = phoneNumber;
        }

        #region IObserverAccount 成员

        public void Update(Subject sueject)
        {
            Console.WriteLine("您于{0}在ATM机取款{1:C}", DateTime.Now, sueject.Money);
        }

        #endregion
    }

 

客户端引用

            Subject subject = new BankAccount(2000);
            subject.AddObserver(new Emailer("
wafe5566@163.com"));
            subject.AddObserver(new Mobile("13993999999"));
            subject.WithDraw();

 

推模式与拉模式(以上为推模式)
    在Observer模式中同样区分推模式和拉模式,我先简单的解释一下两者的区别:
 推模式是当有消息时,把消息信息以参数的形式传递(推)给所有观察者,
 而拉模式是当有消息时,通知消息的方法本身并不带任何的参数,是由观察者自己到主体对象那儿取回(拉)消息。
 我们先看看这种模式带来了什么好处:当有消息时,所有的观察者都会直接得到全部的消息,并进行相应的处理程序,
 与主体对象没什么关系,两者之间的关系是一种松散耦合。但是它也有缺陷,第一是所有的观察者得到的消息是一样的,
 也许有些信息对某个观察者来说根本就用不上,也就是观察者不能“按需所取”;
 第二,当通知消息的参数有变化时,所有的观察者对象都要变化。
 鉴于以上问题,拉模式就应运而生了,它是由观察者自己主动去取消息,需要什么信息,就可以取什么,
 不会像推模式那样得到所有的消息参数。

 

用事件和委托来实现Observer模式更加的简单和优雅,也是一种更好的解决方案。

 

//定义一个委托
    public delegate void NotifyEventHandler(object sender);

    public class ObserverByEvent
    {
        /// <summary>
        /// 通知者类
        /// </summary>
        public class Subject
        {
            public event NotifyEventHandler NotifyEvent;

            private double _money;

            public double Money
            {
                get { return _money; }
                set { _money = value; }
            }

            public Subject(double money)
            {
                this._money = money;
            }

            public void WithDraw()
            {
                OnNotifyChange();
            }
            public void OnNotifyChange()
            {
                //监听是否有事件
                if (NotifyEvent != null)
                {
                    NotifyEvent(this);
                }
            }
        }

        /// <summary>
        /// 具体的观察者类
        /// </summary>
        public class Emailer
        {
            private string _emailer;

            public Emailer(string emailer)
            {
                this._emailer = emailer;
            }

            public void Update(object obj)
            {
                if (obj is Subject)
                {
                    Subject subject = (Subject)obj;
                    Console.WriteLine("您于{0}在ATM机取款{1:C}", DateTime.Now, subject.Money);
                }
            }
        }

        public class Mobile
        {
            private string _phoneNum;

            public Mobile(string phoneNum)
            {
                this._phoneNum = phoneNum;
            }

            /// <summary>
            /// 定义一个和委托类型相同签名的方法
            /// </summary>
            /// <param name="obj"></param>
            public void Update(object obj)
            {
                if (obj is Subject)
                {
                    Subject subject = (Subject)obj;
                    Console.WriteLine("您于{0}在ATM机取款{1:C} RMB", DateTime.Now, subject.Money);
                }
            }
        }
    }

 

//委托事件方法
            ObserverByEvent.Subject subject2 = new ObserverByEvent.Subject(2000);
            subject2.NotifyEvent+=new NotifyEventHandler(new ObserverByEvent.Emailer("
wafe5566@163.com").Update);
            subject2.NotifyEvent+=new NotifyEventHandler(new ObserverByEvent.Mobile("13993997988").Update);
            subject2.WithDraw();

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

观察者模式(Observer Pattern)(三):使用java内置的支持实现HeadFirst气象站

一、问题描述 Weather-O-Rama气象站计划建立下一代的Internet气象观察站,该气象站必须建立在WeatherData对象的基础上,WeatherData对象提供天气数据,有三...

观察者模式(Observer pattern)

观察者模式(Observer patten),定义了对象之间的一对多依赖,这样一来一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。       它在现实生活中也非常常见,如报纸、杂志的订阅...

观察者模式(Observer Pattern)升级版

简介前面的博客https://goo.gl/DFOz50中已经介绍过基本的观察者模式的代码实现,在实际应用中,我们往往希望代码更加简洁,同时也希望能与现有的框架,比如Spring,结合起来。下面介绍如...

观察者模式 | Observer Pattern

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一...

观察者模式(Observer Pattern)

给出问题事例:有一个WeatherData对象可以给我们提供实时的天气情况(温度、湿度、气压),我们要做的就是一个应用,这个应用目前有三个布告板,分别显示目前的状况、气象统计以及简单的预报。这三个布告...

观察者模式(Observer Pattern)

观察者模式定义: Define a one-to-many dependency between objects so that when one object changes state , al...

观察者模式 Observer Pattern

之前总是想写一个程序,大体上是这样的:单服务器,多客户端。服务器上比如说是个房屋价格信息,客户端则是租房子,显示价格。如果现在有特价,怎么客户端怎么实时获取?而且作为客户端,用户定是不止一个,如何通知...

观察者模式(Observer Pattern)

观察者模式 观察者模式(又称发布/订阅模式)定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并自动更新。 观察者模式 概述概述  在许多设计中,经常涉及到多...

观察者模式(Observer Pattern)

1. 概述   有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 ...

2.观察者模式(Observer Pattern)

在观察者模式一章中,Head Fist一书主要是通过“气象台”的例子,来讲解优化代码,并将观察者模式自然而然的融入进去。 本例粗略介绍:有一个屌丝互联网公司赢得了一家气象台的合约,气象台要求如下:气...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)