【设计模式】把风放哨,防老板 --- 观察者模式

一,概述

        观察者<Observer>模式(有时又被称为发布-订阅<Publish/Subscribe>模式、模型-视图<Model/View>模式、源-收听者<Source/Listener>模式或从属者<Dependents>模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

 

二,示例

        题目描述:公司里有的员工偷懒,看股票,看NBA。老板回来需要有人通知他们,然后再好好干活。通知大家的任务交给前台。

 

       1)双向耦合的代码 (读此代码之前先看两个类互相包含)       

             缺点:前台通知类和看股票者相互耦合。如果再想增加一个看NBA的类就违反“开放-- 封闭原则”

  

             StockObserver.h类()

#include <iostream>
#include <string>

using namespace std;

class Secretary;

//看股票的同事
 class StockObserver
 {
        private:
		 string name;
         Secretary *sub;

        public:
		 StockObserver(string name, Secretary *sub)
        {
            this->name = name;//这里一定要加上this
            this->sub = sub;
        }

        void Update()
        {
			
            //cout<<sub->getAction()<<name<<"关闭股票行情,继续工作!"<<endl;

			cout<<name<<"!!关闭股票行情,继续工作!"<<endl;
        }
    };


 

          Secretary.h

#include <iostream>
#include <list>
#include <algorithm>
#include "StockObserver.h"
using namespace std;


template<typename T>
struct display
{
	void operator()( T &observer)
	{
		observer.Update();
	}
	
	
};

class Secretary
{
        //同事列表
        private:
		 list<StockObserver> observers;// = new List<StockObserver>();
         string action;

        public:
        //增加
			friend class StockObserver;
        void Attach(StockObserver observer)
        {
            observers.push_back(observer);
        }

        //减少
        void Detach(StockObserver observer)
        {
            observers.pop_back();
        }

        //通知
        void Notify()
        {
                
            for_each(observers.begin(),observers.end(),display<StockObserver>());
               
        }

        //前台状态
       void  SecretaryAction(string value)
        {
             action = value;
             
        }


    };



           main.cpp(客户端程序)

#include <iostream>
#include "Secretary.h"

using namespace std;

int main()
{

	     //前台小姐童子喆
            Secretary *tongzizhe= new Secretary();
            //看股票的同事
            StockObserver tongshi1("魏关姹", tongzizhe);
            StockObserver tongshi2 ("易管查", tongzizhe);



            //前台记下了两位同事
            tongzizhe->Attach(tongshi1);
            tongzizhe->Attach(tongshi2);
            //发现老板回来
            tongzizhe->SecretaryAction( "老板回来了!");
            //通知两个同事
            tongzizhe->Notify();

	    getchar();//防止退出的
	    return 0;
}


            2)解除耦合实践一:(C#)

 

        增加了抽象的观察者,方便扩展各种类型的扩展者。

using System;
using System.Collections.Generic;
using System.Text;

namespace 观察者模式
{
    class Program
    {
        static void Main(string[] args)
        {
            //前台小姐童子喆
            Secretary tongzizhe = new Secretary();
            //看股票的同事
            StockObserver tongshi1 = new StockObserver("魏关姹", tongzizhe);
            //看NBA的同事
            NBAObserver tongshi2 = new NBAObserver("易管查", tongzizhe);

            //前台记下了两位同事
            tongzizhe.Attach(tongshi1);
            tongzizhe.Attach(tongshi2);
            //发现老板回来
            tongzizhe.SecretaryAction = "老板回来了!";
            //通知两个同事
            tongzizhe.Notify();


            Console.Read();
        }
    }

    //前台秘书类
    class Secretary
    {
        //同事列表
        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 SecretaryAction
        {
            get { return action; }
            set { action = value; }
        }

    }

    //抽象观察者
    abstract class Observer
    {
        protected string name;
        protected Secretary sub;

        public Observer(string name, Secretary sub)
        {
            this.name = name;
            this.sub = sub;
        }

        public abstract void Update();
    }


    //看股票的同事
    class StockObserver : Observer
    {
        public StockObserver(string name, Secretary sub)
            : base(name, sub)
        {
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SecretaryAction, name);
        }
    }

    //看NBA的同事
    class NBAObserver : Observer
    {
        public NBAObserver(string name, Secretary sub)
            : base(name, sub)
        {
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SecretaryAction, name);
        }
    }
}


                  3)解除耦合实践二:(C#)

                                    改进:由于老板来了会自己通知职员,前台也可以偷偷通知职员老板来了。所以增加一个通知者接口。


 

using System;
using System.Collections.Generic;
using System.Text;

namespace 观察者模式
{
    class Program
    {
        static void Main(string[] args)
        {
            //老板胡汉三
            Boss huhansan = new Boss();

            //看股票的同事
            StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
            //看NBA的同事
            NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);

            huhansan.Attach(tongshi1);
            huhansan.Attach(tongshi2);

            huhansan.Detach(tongshi1);

            //老板回来
            huhansan.SubjectState = "我胡汉三回来了!";
            //发出通知
            huhansan.Notify();

            Console.Read();
        }
    }

    //通知者接口
    interface Subject
    {
        void Attach(Observer observer);
        void Detach(Observer observer);
        void Notify();
        string SubjectState
        {
            get;
            set;
        }
    }

    class Secretary : 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; }
        }
    }

    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; }
        }
    }

    //抽象观察者
    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();
    }

    //看股票的同事
    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
    {
        public NBAObserver(string name, Subject sub)
            : base(name, sub)
        {
        }

        public override void Update()
        {
            Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);
        }
    }
}

 

三,观察者模式

 

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

        

观察者基本代码:抽象通知者类,具体实现通知者类,抽象观察者类,具体实现观察者类

                             抽象通知者为具体实现者父类,负责通知注册的观察者类

              

    class Program
    {
        static void Main(string[] args)
        {
            ConcreteSubject s = new ConcreteSubject();

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

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

            Console.Read();

        }
    }


    abstract class Subject             //抽象通知者
    {
        private IList<Observer> observers = new List<Observer>();

        //增加观察者
        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();
            }
        }
    }

    //具体通知者
    class ConcreteSubject : Subject
    {
        private string subjectState;

        //具体通知者状态
        public string SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }
    }


    abstract class Observer   //抽象观察者
    {
        public abstract void Update();
    }

    class ConcreteObserver : Observer  //具体观察者
    {
        private string name;
        private string observerState;
        private ConcreteSubject subject;

        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);
        }

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


四,观察者模式的特点

         问题:

        1)将一个系统分割成一系列相互协作的类有一个不好的副作用:需要维护相对对象的一致性

        2)我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便

        观察者优点:

         1)让耦合的双方都依赖于抽象,而不是依赖于具体。抽象不变,具体会变化

 



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值