不是使用实例变量)来存储观察者引用有什么优点。假定除当前用户接口StockDisplay外,我们还需要绘制股价在交易日内变化的实时图形。为此,我们创建了一个名为StockGraph的新类,它绘制股价(y轴)和当天时间(x轴)的图形。在应用程序启动时,它同时在Stock实例中注册StockDisplay和StockGraph类的实例。因为主体在容器(与实例变量相对)中存储观察者,所以这不会出现问题。当股价发生变化时,Stock实例向其容器中的两个观察者实例通知所发生的状态变化。正如我们所看到的一样,使用容器可提供更大的灵活性,即每个主体可支持多个观察者。这使主体有可能向无数多个观察者通知所发生的状态变化,而不是只通知一个观察者。
虽然不是强制要求,但很多框架为观察者和主体提供了一组要实现的接口。正如下面的C#代码示例所示,IObserver接口公开一种公共方法Notify。此接口是由所有要用作观察者的类实现的。IObservable接口(是由所有要用作主体的类实现的)公开两种方法Register和UnRegister。这些接口通常采用抽象虚拟类或真实接口的形式(如果实现语言支持此类构造的话)。利用这些接口有助于减少观察者和主体之间的耦合关系。与观察者和主体类之间的紧密耦合关系不同,IObserver和IObservable接口允许执行独立于实现的操作。通过对接口的分析,您将注意到键入的所有方法针对的是接口类型(与具体类相对)。这种方法将接口编程模型的优点扩展到Observer模式。
IObserver和IObservable接口(C#)
//interface the all observer classes should implement
public interface IObserver {
void Notify(object anObject);
}//IObserver
//interface that all observable classes should implement
public interface IObservable {
void Register(IObserver anObserver);
void UnRegister(IObserver anObserver);
}//IObservable
再回到我们的示例应用程序,我们知道Stock类用作主体。因此,它将实现IObservable接口。类似地,StockDisplay类实现IObserver接口。因为所有操作都是由该接口定义的(而不是由具体类定义的),所以Stock类并未与StockDisplay类绑定在一起,反之亦然。这使我们能够快速地更改特定的观察者或主体实现,而不会影响应用程序的其他部分(使用不同的观察者替换StockDisplay或添加额外的观察者实例)。
除了这些接口外,框架还经常为主体提供一个通用基类,减少了支持Observer模式所需的工作。基类实现IObservable接口,以提供支持观察者实例存储和通知所需的基础结构。下面的C#代码示例简要介绍一个名为ObservableImpl的基类。尽管可能任何容器都可以完成这一任务,但该类在Register和UnRegister方法中将观察者存储委托给哈希表实例(为了方便起见,我们在示例中使用哈希表作为容器,它只使用一个方法调用来撤消注册特定的观察者实例)。还要注意添加了NotifyObservers方法。此方法用于通知哈希表中存储的观察者。在调用此方法时,将枚举该容器,并对观察者实例调用Notify方法。
ObservableImpl类(C#)
//helper class that implements observable interface
public class ObservableImpl:IObservable {
//container to store the observer instance (is not synchronized for
this example)
protected Hashtable _ObserverContainer=new Hashtable();
//add the observer
public void Register(IObserver anObserver){
_ObserverContainer.Add(anObserver,anObserver);
}//Register
//remove the observer
public void UnRegister(IObserver anObserver){
_ObserverContainer.Remove(anObserver);
}//UnRegister
//common method to notify all the observers
public void NotifyObservers(object anObject) {
//enumeration the observers and invoke their notify method
foreach(IObserver anObserver in _ObserverContainer.Keys) {
anObserver.Notify(anObject);
}//foreach
}//NotifyObservers
}//ObservableImpl
我们的示例应用程序使用以下方法来利用此基类基础结构:修改Stock类以扩展ObservableImpl类,而不是提供其自己的特定IObservable接口实现。因为ObservableImpl类实现了IObservable接口,所以不需要对StockDisplay类进行任何更改。实际上,这种方法简化了Observer模式的实现,在保持类之间松散耦合关系的同时,使多个主体重复使用相同的功能。
下面的.NET观察者示例重点说明了IObservable和IObserver接口以及ObservableBase类在我们的股票应用程序中的使用情况。除了Stock和StockDisplay类外,此示例使用MainClass将观察者和主体实例关联起来,并修改Stock实
虽然不是强制要求,但很多框架为观察者和主体提供了一组要实现的接口。正如下面的C#代码示例所示,IObserver接口公开一种公共方法Notify。此接口是由所有要用作观察者的类实现的。IObservable接口(是由所有要用作主体的类实现的)公开两种方法Register和UnRegister。这些接口通常采用抽象虚拟类或真实接口的形式(如果实现语言支持此类构造的话)。利用这些接口有助于减少观察者和主体之间的耦合关系。与观察者和主体类之间的紧密耦合关系不同,IObserver和IObservable接口允许执行独立于实现的操作。通过对接口的分析,您将注意到键入的所有方法针对的是接口类型(与具体类相对)。这种方法将接口编程模型的优点扩展到Observer模式。
IObserver和IObservable接口(C#)
//interface the all observer classes should implement
public interface IObserver {
void Notify(object anObject);
}//IObserver
//interface that all observable classes should implement
public interface IObservable {
void Register(IObserver anObserver);
void UnRegister(IObserver anObserver);
}//IObservable
再回到我们的示例应用程序,我们知道Stock类用作主体。因此,它将实现IObservable接口。类似地,StockDisplay类实现IObserver接口。因为所有操作都是由该接口定义的(而不是由具体类定义的),所以Stock类并未与StockDisplay类绑定在一起,反之亦然。这使我们能够快速地更改特定的观察者或主体实现,而不会影响应用程序的其他部分(使用不同的观察者替换StockDisplay或添加额外的观察者实例)。
除了这些接口外,框架还经常为主体提供一个通用基类,减少了支持Observer模式所需的工作。基类实现IObservable接口,以提供支持观察者实例存储和通知所需的基础结构。下面的C#代码示例简要介绍一个名为ObservableImpl的基类。尽管可能任何容器都可以完成这一任务,但该类在Register和UnRegister方法中将观察者存储委托给哈希表实例(为了方便起见,我们在示例中使用哈希表作为容器,它只使用一个方法调用来撤消注册特定的观察者实例)。还要注意添加了NotifyObservers方法。此方法用于通知哈希表中存储的观察者。在调用此方法时,将枚举该容器,并对观察者实例调用Notify方法。
ObservableImpl类(C#)
//helper class that implements observable interface
public class ObservableImpl:IObservable {
//container to store the observer instance (is not synchronized for
this example)
protected Hashtable _ObserverContainer=new Hashtable();
//add the observer
public void Register(IObserver anObserver){
_ObserverContainer.Add(anObserver,anObserver);
}//Register
//remove the observer
public void UnRegister(IObserver anObserver){
_ObserverContainer.Remove(anObserver);
}//UnRegister
//common method to notify all the observers
public void NotifyObservers(object anObject) {
//enumeration the observers and invoke their notify method
foreach(IObserver anObserver in _ObserverContainer.Keys) {
anObserver.Notify(anObject);
}//foreach
}//NotifyObservers
}//ObservableImpl
我们的示例应用程序使用以下方法来利用此基类基础结构:修改Stock类以扩展ObservableImpl类,而不是提供其自己的特定IObservable接口实现。因为ObservableImpl类实现了IObservable接口,所以不需要对StockDisplay类进行任何更改。实际上,这种方法简化了Observer模式的实现,在保持类之间松散耦合关系的同时,使多个主体重复使用相同的功能。
下面的.NET观察者示例重点说明了IObservable和IObserver接口以及ObservableBase类在我们的股票应用程序中的使用情况。除了Stock和StockDisplay类外,此示例使用MainClass将观察者和主体实例关联起来,并修改Stock实
| 对此文章发表了评论 |

