技术开发 频道

行为型模式篇-观察者模式(Oberver Pattern)

    Observer模式解说

    下面通过一个例子来说明Observer模式。监控某一个公司的股票价格变化,可以有多种方式,通知的对象可以是投资者,或者是发送到移动设备,还有电子邮件等。一开始我们先不考虑Observer模式,通过一步步地重构,最终重构为Observer模式。现在有这样两个类:Microsoft和Investor,如下图所示:
图3 UML静态图示例

    它们的实现如下:
public class Microsoft { private Investor _investor; private String _symbol; private double _price; public void Update() { _investor.SendData(this); } public Investor Investor { get { return _investor; } set { _investor = value; } } public String Symbol { get { return _symbol; } set { _symbol = value; } } public double Price { get { return _price; } set { _price = value; } } } public class Investor { private string _name; public Investor(string name) { this._name = name; } public void SendData(Microsoft ms) { Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", _name, ms.Symbol,ms.Price); } }

    简单的客户端实现:

class Program { static void Main(string[] args) { Investor investor = new Investor("Jom"); Microsoft ms = new Microsoft(); ms.Investor = investor; ms.Symbol = "Microsoft"; ms.Price = 120.00; ms.Update(); Console.ReadLine(); } }

    运行后结果如下:
Notified Jom of Microsoft's change to ¥120

    可以看到,这段代码运行并没有问题,也确实实现了我们最初的设想的功能,把Microsoft的股票价格变化通知到了Jom投资者那儿。但是这里面出现了如下几个问题:

    1.Microsoft和Investor之间形成了一种双向的依赖关系,即Microsoft调用了Investor的方法,而Investor调用了Microsoft类的属性。如果有其中一个类变化,有可能会引起另一个的变化。
    2.当出现一种的通知对象,比如说是移动设备Mobile:

public class Mobile { private string _no; public Mobile(string No) { this._no = No; } public void SendData(Microsoft ms) { Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", _no, ms.Symbol, ms.Price); } }

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

public class Microsoft { private Investor _investor; private Mobile _mobile; private String _symbol; private double _price; public void Update() { _investor.SendData(this); _mobile.SendData(this); } public Mobile Mobile { get { return _mobile; } set { _mobile = value; } } public Investor Investor { get { return _investor; } set { _investor = value; } } public String Symbol { get { return _symbol; } set { _symbol = value; } } public double Price { get { return _price; } set { _price = value; } } }

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

    实现代码如下:

public interface IObserver { void SendData(Microsoft ms); } public class Investor : IObserver { private string _name; public Investor(string name) { this._name = name; } public void SendData(Microsoft ms) { Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", _name, ms.Symbol,ms.Price); } } public class Microsoft { private IObserver _investor; private String _symbol; private double _price; public void Update() { _investor.SendData(this); } public String Symbol { get { return _symbol; } set { _symbol = value; } } public double Price { get { return _price; } set { _price = value; } } public IObserver Investor { get { return _investor; } set { _investor = value; } } }
0
相关文章