MaoBisheng

Asp.Net(C#) & SQL & Oracle

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  

18. Observer 观察者模式                     2008-09-15

动机(Motivation)

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

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

意图(Intent

定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。        ——《设计模式》GoF

 

示意代码:

    //Subject类,它把所有对观察者对象的引用保存在一个聚焦里,每个主题都可以
    
//有任何数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象
    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();
        }

    }

 

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

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

    }

 

    //Observer类,抽象观察者,为所有的具体观察定义一个接口,在得到主题的通知时更新自己
    abstract class Observer
    
{
        
public abstract void Update();
    }

 

    //ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,
    
//以便使本身的状态与主题的状态相协调
    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; }
        }

    }

 

客户端代码:

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

    }

 

Observer 的几个要点

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

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

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

适用性

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

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

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

 

posted on 2008-09-15 15:38  MaoBisheng  阅读(413)  评论(0编辑  收藏  举报