概述g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
意图g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。[GOF 《设计模式》]g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
结构图g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

图1 Observer模式结构图

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
生活中的例子g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
观察者定义了对象间一对多的关系,当一个对象的状态变化时,所有依赖它的对象都得到通知并且自动地更新。拍卖演示了这种模式。每个投标人都有一个标有数字的牌子用于出价。拍卖师开始拍卖时,他观察是否有牌子举起出价。每次接受一个新的出价都改变了拍卖的当前价格,并且广播给所有的投标人进行新的出价。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
图2 使用拍卖例子的观察者模式

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Observer模式解说g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
下面通过一个例子来说明Observer模式。监控某一个公司的股票价格变化,可以有多种方式,通知的对象可以是投资者,或者是发送到移动设备,还有电子邮件等。一开始我们先不考虑Observer模式,通过一步步地重构,最终重构为Observer模式。现在有这样两个类:Microsoft和Investor,如下图所示:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

图3 UML静态图示例

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
它们的实现如下:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Microsoftg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private Investor _investor;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private String _symbol;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private double _price;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void Update()g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        _investor.SendData(
this);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Investor Investorg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _investor; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _investor = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public String Symbolg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _symbol; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _symbol = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public double Priceg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _price; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _price = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Investorg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private string _name;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Investor(string name)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
this._name = name;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void SendData(Microsoft ms)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Console.WriteLine(
"Notified {0} of {1}'s " + "change to {2:C}", _name, ms.Symbol,ms.Price);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
简单的客户端实现:
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
class Programg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
static void Main(string[] args)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Investor investor
= new Investor("Jom");g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Microsoft ms
= new Microsoft();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Investor
= investor;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Symbol
= "Microsoft";g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Price
= 120.00;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Update();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Console.ReadLine();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

运行后结果如下:

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Notified Jom of Microsoft's change to ¥120g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
可以看到,这段代码运行并没有问题,也确实实现了我们最初的设想的功能,把Microsoft的股票价格变化通知到了Jom投资者那儿。但是这里面出现了如下几个问题:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
1.Microsoft和Investor之间形成了一种双向的依赖关系,即Microsoft调用了Investor的方法,而Investor调用了Microsoft类的属性。如果有其中一个类变化,有可能会引起另一个的变化。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
2.当出现一种的通知对象,比如说是移动设备Mobile:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Mobileg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private string _no;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Mobile(string No)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
this._no = No;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void SendData(Microsoft ms)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Console.WriteLine(
"Notified {0} of {1}'s " + "change to {2:C}", _no, ms.Symbol, ms.Price);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

这时候对应的Microsoft的类就应该改变为如下代码,在Microsot类中增加Mobile,同时修改Update()方法使其可以通知到移动设备:

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Microsoftg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private Investor _investor;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private Mobile _mobile;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private String _symbol;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private double _price;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void Update()g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        _investor.SendData(
this);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        _mobile.SendData(
this);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Mobile Mobileg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _mobile; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _mobile = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Investor Investorg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _investor; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _investor = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public String Symbolg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _symbol; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _symbol = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public double Priceg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _price; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _price = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

显然这样的设计极大的违背了“开放-封闭”原则,这不是我们所想要的,仅仅是新增加了一种通知对象,就需要对原有的Microsoft类进行修改,这样的设计是很糟糕的。对此做进一步的抽象,既然出现了多个通知对象,我们就为这些对象之间抽象出一个接口,用它来取消Microsoft和具体的通知对象之间依赖。

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

图4 静态UML图示例

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
实现代码如下:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public interface IObserverg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
void SendData(Microsoft ms);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Investor : IObserverg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private string _name;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public Investor(string name)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
this._name = name;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void SendData(Microsoft ms)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Console.WriteLine(
"Notified {0} of {1}'s " + "change to {2:C}", _name, ms.Symbol,ms.Price);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Microsoftg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private IObserver _investor;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private String _symbol;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private double _price;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void Update()g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        _investor.SendData(
this);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public String Symbolg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _symbol; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _symbol = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public double Priceg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _price; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _price = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public IObserver Investorg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _investor; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _investor = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

做到这一步,可以看到,我们在降低两者的依赖性上已经迈进了一小步,正在朝着弱依赖性这个方向变化。在Microsoft类中已经不再依赖于具体的Investor,而是依赖于接口IObserver。

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
但同时我们看到,再新出现一个移动设备这样的通知对象,Microsoft类仍然需要改变,对此我们再做如下重构,在Microsoft中维护一个IObserver列表,同时提供相应的维护方法。g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

图5 静态UML示例图

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
Microsoft类的实现代码如下:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public class Microsoftg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private List<IObserver> observers = new List<IObserver>();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private String _symbol;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
private double _price;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void Update()g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
foreach (IObserver ob in observers)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
            ob.SendData(
this);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void AddObserver(IObserver observer)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        observers.Add(observer);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public void RemoveObserver(IObserver observer)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        observers.Remove(observer);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public String Symbolg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _symbol; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _symbol = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
public double Priceg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
get { return _price; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
       
set { _price = value; }g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

此时客户端的调用代码:

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
class Programg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
static void Main(string[] args)g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
   
{g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        IObserver investor1
= new Investor("Jom");g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        IObserver investor2
= new Investor("TerryLee");g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Microsoft ms
= new Microsoft();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Symbol
= "Microsoft";g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Price
= 120.00;g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.AddObserver(investor1);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.AddObserver(investor2);g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        ms.Update();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
        Console.ReadLine();g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
    }
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
}
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

走到这一步,已经有了Observer模式的影子了,Microsoft类不再依赖于具体的Investor,而是依赖于抽象的IOberver。存在着的一个问题是Investor仍然依赖于具体的公司Microsoft,况且公司还会有很多IBM,Google等,解决这样的问题很简单,只需要再对Microsoft类做一次抽象。如下图所示:

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ

图6 静态UML示例图

g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
实现代码如下:g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
public abstract class Stockg©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ
g©™½¹”¯Š˜www.netcsharp.cn{äœØ±ðŽæŸ