代码改变世界

《深入浅出设计模式-中文版》读书笔记-观察者模式(四)

2010-07-06 06:34  Virus-BeautyCode  阅读(2523)  评论(1编辑  收藏  举报

  今天要接触的是观察者模式Observer。

  提到观察者,肯定会想到还应该有被观察者,也就是观察的内容,或者说是观察的主题。

  首先让我们看看报纸和杂志的订阅是怎么回事:

  •   报社的业务就是出版报纸。
  •   向一家报社订阅报纸,只要有新报纸,就会给你送过来。只要你是他们的订阅者,就一直会收到。
  •   当你不想继续看报纸的时候,可以取消订阅,他们就不会再送报纸过来。
  •   只要报社存在,就会一直有人订阅或者是取消订阅。

  上面就是一个典型的观察者模式,你、我、他,这些订阅报纸的人就是观察者Observer,报社就是被观察者,观察的主题Subject。

  观察者模式的定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态的时候,它的所有依赖者都会收到通知并自动更新。

  观察者有很多的实现方式,最常见的是包含Subject与Observer接口的类设计。

  

 

  上图是我从书中摘取出来的。

  •   当两个对象之间松耦合,他们依然可以交互,但是不清楚彼此的细节。观察者模式提供了一种对象设计,实现主题和观察者之间的松耦合。
  •   对于观察者的一切,主题只是知道观察者实现了某一个接口(也就是Observer接口)。主题不需要知道观察者具体是做什么的类。
  •   任何时候我们都可以添加新的观察者,主题只是依赖于观察者列表,添加观察者也就是在列表中添加元素。同样,也可以删除观察者,也就是删除观察者列表的元素。
  •   有新类型的观察者,主题不用修改代码,只要新的观察者实现Observer接口就可以了。只需要在主题中注册观察者,然后就可以收到新通知了。
  •   二者是松耦合的,相互之间不影响,只要接口被遵守,就可以自由的改变他们。

  设计原则:

  为了交互对象之间的松耦合设计而努力。

  

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.DesignPattern.Head.First.Observer
{
    
public interface  IObserver
    {
        
void Update();
    }
}


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

namespace BeautyCode.DesignPattern.Head.First.Observer
{
    
public interface  ISubject
    {
        IList
<IObserver> Observers { get;  set; }
        
void Register(IObserver observer);
        
void UnRegister(IObserver observer);
        
void NotifyObserver();
    }
}


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

namespace BeautyCode.DesignPattern.Head.First.Observer
{
   
public  class SubjectImpl:ISubject 
    {
       
public SubjectImpl()
       {
           _observers 
= new List<IObserver>(0);
       }
       
private IList<IObserver> _observers;
        
public IList<IObserver> Observers
        {
            
get { return _observers; }
             
set { this._observers=value ; }
        }

        
public void Register(IObserver observer)
        {
            _observers.Add(observer);
        }

        
public void UnRegister(IObserver observer)
        {
            _observers.Remove(observer);
        }

        
public void NotifyObserver()
        {
            
if (_observers != null)
            {
                
foreach (IObserver ob in _observers)
                {
                    ob.Update();
                }
            }
        }
    }
}


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

namespace BeautyCode.DesignPattern.Head.First.Observer
{
   
public  class ObserverImpl:IObserver 
    {
       
private string _name;
       
public ObserverImpl(string name)
       {
           _name 
= name;
       }
        
public void Update()
        {
            Console.WriteLine(
"{0}收到通知了",_name );
        }
    }
}

 

  客户端调用代码

  

代码
 Console.WriteLine("====Head.First.Observer=================================================");
            Head.First.Observer.ISubject subject 
= new Head.First.Observer.SubjectImpl();
            Head.First.Observer.IObserver ob1 
= new Head.First.Observer.ObserverImpl("ob1");
            Head.First.Observer.IObserver ob2 
= new Head.First.Observer.ObserverImpl("ob2");
            Head.First.Observer.IObserver ob3 
= new Head.First.Observer.ObserverImpl("ob3");
            subject.Register(ob1);
            subject.Register(ob2);
            subject.Register(ob3);
            subject.NotifyObserver();

 

  从上面的代码结构中可以看出来如果需要增加一个新的观察者,只需要新观察者实现IObserver接口,然后再主题中register就可以了。

  但是上面的观察者模式也还是有一点强依赖的意味,就是主题类依赖于观察者列表,有新的观察者就需要主题类主动注册。又没有可能主题也不关心有没有什么新观察者,只是专注于属于自己的职责-通知主题的内容变化。

  其实在.NET中有一种天然存在的设计模式,就是观察者。大家都知道.NET是事件驱动的形式,就是控件的事件引发方法的调用,让触发事件的一方得到信息。我们可以将这个原理引入观察者模式的实现上来。

  

耗子,猫、狗、主人的故事
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp

    
public delegate void ObserverEventHandler(object sender, EventObjectArgs e);
    
/// <summary>
    
/// 被观察者
    
/// </summary>
    public interface IEventObserable
    {

         
event ObserverEventHandler ObserverEvent;
         
void OnObserverEvent(EventObjectArgs e);
         
void RaiseObserverMethod();
    }
    
/// <summary>
    
/// 观察者
    
/// </summary>
    public interface IEventObserver
    {
        
    }
    
    
public class EventObjectArgs : EventArgs
    {
        
private string _message;
        
public string Message
        {
            
get { return _message; }
        }
        
public EventObjectArgs()
        {
        }
        
public EventObjectArgs(string message)
        {
            
this._message = message;
        }
    }
    
class EventCat : IEventObserable
    {
        
#region IEventObserable 成员

        
public event ObserverEventHandler ObserverEvent;

        
public  void OnObserverEvent(EventObjectArgs e)
        {
            
if (null != ObserverEvent)
            {

                ObserverEvent(
this, e);
            }
        }

        
public void RaiseObserverMethod()
        {
            Console.WriteLine(
"猫叫了");
            OnObserverEvent(
new EventObjectArgs("猫叫了"));
        }

        
#endregion
    }
    
class EventMouse : IEventObserver
    {
        
public EventMouse() { }
        
public EventMouse(IEventObserable  observable)
        {
            observable.ObserverEvent 
+= new ObserverEventHandler(observable_ObserverEvent);
        }

       
public  void observable_ObserverEvent(object sender, EventObjectArgs e)
        {
            Console.WriteLine(
string.Format("{0},所有老鼠被吓跑了", e.Message));
        }
    }
    
class EventDog : IEventObserver
    {
        
public EventDog(IEventObserable observable)
        {
            observable.ObserverEvent 
+= new ObserverEventHandler(observable_ObserverEvent);
        }

        
public void observable_ObserverEvent(object sender, EventObjectArgs e)
        {
            Console.WriteLine(
string.Format("{0},所有老鼠被吓跑了,但是狗拿耗子多管闲事", e.Message));
        }
    }
    
class EventMaster : IEventObserver
    {
        
public EventMaster(IEventObserable observable)
        {
            observable.ObserverEvent 
+= new ObserverEventHandler(observable_ObserverEvent);
        }

       
public  void observable_ObserverEvent(object sender, EventObjectArgs e)
        {
            Console.WriteLine(
string.Format("{0},所有老鼠被吓跑了,但是狗拿耗子多管闲事,主人生气了,要打死这些动物", e.Message));
        }
    }
}
  

 

  OO原则:

  封装变化

  多用组合,少用继承

  针对接口编程,不针对实现编程

  为交互对象之间的松耦合设计而努力

  OO模式

  观察者模式-在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。