观察者模式

来源:互联网 发布:linux 物理内存管理 编辑:程序博客网 时间:2024/06/05 20:56

一、观察者模式简介

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

二、解决的问题

         当一个对象的改变需要同时改变其他对象的时候,而且不知道有多少对象有待改变时,应该考虑使用观察者模式。观察者模式所做的工作其实就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使的各自的变化都不会影响另一边的变化。

三、观察者模式分析

下面通过一个例子来说明Observer模式。监控某一个公司的股票价格变化,可以有多种方式,通知的对象可以是投资者,或者是发送到移动设备,还有电子邮件等。为了降低耦合性,代码设计如下:

public abstract class Stock{    private List<IObserver> observers = new List<IObserver>();    private String _symbol;    private double _price;    public Stock(String symbol, double price)    {        this._symbol = symbol;        this._price = price;    }    public void Update()    {        foreach (IObserver ob in observers)        {            ob.SendData(this);        }    }    public void AddObserver(IObserver observer)    {        observers.Add(observer);    }    public void RemoveObserver(IObserver observer)    {        observers.Remove(observer);    }    public String Symbol    {        get { return _symbol; }    }    public double Price    {        get { return _price; }    }}public class Microsoft : Stock{    public Microsoft(String symbol, double price)        : base(symbol, price)    { }}public interface IObserver{    void SendData(Stock stock);}public class Investor : IObserver{    private string _name;    public Investor(string name)    {        this._name = name;    }    public void SendData(Stock stock)    {        Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", _name, stock.Symbol,stock.Price);    }}

客户端程序代码如下:

class Program{    static void Main(string[] args)    {        Stock ms = new Microsoft("Microsoft",120.00);        ms.AddObserver(new Investor("Jom"));        ms.AddObserver(new Investor("TerryLee"));        ms.Update();        Console.ReadLine();   } }


从上面的代码可以看出,通过抽象类,将直接依赖变为了间接依赖,每一个具体的对象与具体的观察者都没有直接联系,这样大大提供了系统的可维护性和可扩展性。那还有没有更好的方式呢?利用事件和委托来实现Observer模式我认为更加的简单和优雅,也是一种更好的解决方案。看下面代码

class Program{    static void Main(string[] args)    {        Stock stock = new Stock("Microsoft", 120.00);        Investor investor = new Investor("Jom");        stock.NotifyEvent += new NotifyEventHandler(investor.SendData);        stock.Update();        Console.ReadLine();    }}public delegate void NotifyEventHandler(object sender);public class Stock{    public NotifyEventHandler NotifyEvent;    private String _symbol;    private double _price;    public Stock(String symbol, double price)    {        this._symbol = symbol;        this._price = price;    }    public void Update()    {        OnNotifyChange();        }    public void OnNotifyChange()    {        if (NotifyEvent != null)        {            NotifyEvent(this);        }    }    public String Symbol    {        get { return _symbol; }    }    public double Price    {        get { return _price; }    }} public class Investor{    private string _name;    public Investor(string name)    {        this._name = name;    }    public void SendData(object obj)    {        if (obj is Stock)        {            Stock stock = (Stock)obj;            Console.WriteLine("Notified {0} of {1}'s " + "change to {2:C}", _name, stock.Symbol, stock.Price);        }    }}


 

效果及实现要点

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

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

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

适用性

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

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

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

总结

通过Observer模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。


 

原创粉丝点击