Observer观察者模式

观察者模式又叫发布-订阅(Publish/Subscribe)模式

动机(Motivation)

在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。

使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。

意图(Intent)

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

结构(Structure)

1.Subject类,它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

2.ConcreteSubject类:具体主题,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

3.Observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己

4.ConcreteObserver类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使自身的状态与主题的状态相协调

代码实现

实例:小张在上班时间看股票行情,小刘在看NBA直播,为了不让老板回来的时候发现,摆脱前台的秘书,当老板回来的时候通风报信。有一次,秘书因为被老板叫去没有高速小张和小刘,不幸地,正在看股票的小张被老板发现了。

在这个实例当中,老板和秘书都是通知者(被老板发现可以看做老板亲自通知),小张和小刘是观察者,根据通知,小张和小刘决定是否采取行动。

通知者接口:Subject类,抽象主题提供一个接口,可以增加和删除观察者对象。

    interface Subject
    {
        void Attach(Observer observer);
        void Detach(Observer observer);
        void Notify();
        string SubjectState
        {
            get;
            set;
        }
    }

具体的通知者类:ConcreteSubject类具体主题,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。(本例中,具体的通知者类可能是前台,也可能是老板,他们也许有各自的一些方法,但是对于通知类来说,他们是一样的,所以它们都去实现通知者这个接口)

    class Boss : Subject
    {
        //同事列表
        private IList<Observer> observers = new List<Observer>();
        private string action;
        //增加
        public void Attach(Observer observer)
        {
            observers.Add(observer);
        }
        //减少
        public void Detach(Observer observer)
        {
            observers.Remove(observer);
        }
        //通知
        public void Notify()
        {
            foreach (Observer o in observers)
            {
                o.Update();
            }
        }
        //老板状态
        public string SubjectState
        {
            get { return action; }
            set { action = value; }
        }
    }

前台秘书类同老板类,代码省略。

抽象观察者:Observer类者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己

     abstract class Observer
    {
        protected string name;
        protected Subject sub;
        public Observer(string name, Subject sub)
        {
            this.name = name;
            this.sub = sub;
        }
        public abstract void Update();
    }

看股票的同时和看NBA的同事: ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口。(本例中,NBAObserver和 StockObserve实现Observer接口,并且根据通知采取行动关闭股票行情,继续工作或关闭NBA直播,继续工作)

    //看股票的同事
    class StockObserver:Observer
    {
        public StockObserver(string name, Subject sub) : base(name, sub) { }
        public override void Update()
        {
            Console.WriteLine("{0}{1}关闭股票行情,继续工作!",sub.SubjectState,name);
        }
    }
    //看NBA的同事
    class NBAObserver : Observer
    {
        //关闭NBA直播,继续工作
    }

客户端代码

实例化出来三个对象:张老板,看股票的同事小张,看NBA直播的同事小刘

            Boss zhangBoss = new Boss();
            StockObserver colleague1 = new StockObserver("同事小张", zhangBoss);
            NBAObserver colleague2 = new NBAObserver("同事小刘", zhangBoss);

 增加两个观察者对象:同事小张和同事小刘,小张被老板发现了,从观察者中删除

            zhangBoss.Attach(colleague1);
            zhangBoss.Attach(colleague2);
            zhangBoss.Detach(colleague1);

老板回来发出通知

            zhangBoss.SubjectState = "老板我回来了!";
            zhangBoss.Notify();

运行结果

observer模式的几个要点

1.使用面向对象的抽象,Observer模式使得我们可以独立地改变目标和观察者,从而使二者之间的依赖关系达到松耦合。

2.目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。观察者自己决定是否需要订阅通知,目标对象对此一无所知。

3.在C#的event中,委托充当了抽象的Observer接口,而提供事件的对象充当了目标对象。委托是比抽象Observer接口更为松耦合的设计。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值