软件设计和开发人员在设计阶段需要把当前需求以及将来的变化的需求考虑清楚,设计出可扩展性的系统,根据Open-Closed Principle ,应该把不变的需求(WarningManager)封装起来。同时适应变化的需求(不同的通知方式)。这样就引入了Observer模式来解决这一类问题。Observer模式可以广泛应用于消息通知系统,消息通知系统主要有两部分组成,一部分是消息源,另外一部分为消息处理类。消息源就如WarningManager,负责管理和产生消息。消息处理类就像AudioManager和DisplayManager那样,从消息源那里得到消息,然后进行处理。
上图为Observer模式通用实现,消息源抽象成Subject类而消息处理类抽象成Observer类。由于C#在语法层built-in了Observer模式(使用delegate和event),所以,在实现上大大的简化了。上述例子使用Observer的实现如下。
public sealed class Warning
{
public int Level{set; get;}
public int Type{set; get;}
}
public class AudioManager
{
public AudioManager()
{
WarningManager.WarningEvent += HandleWarning;
}
public void HandleWarning(Warning warning)
{
Console.WriteLine("Play warning audio.");
}
}
public class DisplayManager
{
public DisplayManager()
{
WarningManager.WarningEvent += HandleWarning;
}
public void HandleWarning(Warning warning)
{
Console.WriteLine("Show warning picture.");
}
}
public class SMSManager
{
public SMSManager()
{
WarningManager.WarningEvent += HandleWarning;
}
public void HandleWarning(Warning warning)
{
Console.WriteLine("Send out SMS.");
}
}
public sealed class WarningManager
{
public delegate void WarningEventHandler(Warning warning);
public static event WarningEventHandler WarningEvent;
private void Notify(Warning warning)
{
WarningEventHandler warningEvent = WarningEvent;
if (warningEvent != null)
{
warningEvent(warning);
}
}
}
从上图看,WarningManager不再需要保存消息处理类的引用了,也就是说客户想增加新的通知手段,WarningManager不需要进行任何的修改。WarningManager 定义一个event提供给各个消息处理类进行订阅。消息处理类订阅该消息WarningManager.WarningEvent += HandleWarning;每当有告警产生的时候,WarningManager可以通知到各个订阅消息的消息处理类。哪怕某天客户想增加新需求,例如当收到告警的时候发送email,系统只要增加EmailManager处理类,WarningManager不需要任何的修改。
Observer模式应用广泛消息通知系统,我认为MS之所以把Observer直接built-in到C#语法里面,是因为Observer广泛的使用在界面(Winform和Webform)用户动作的处理上,在Forms上对每一个控件的用户动作事件处理都是注册事件到一个处理函数。
这样Form就可以处理用户的异步动作。这也符合Hollywood Principle(Don't call us, we'll call you)。把form和具体的控件解耦,因为form的设计是相对固定的,但是控件可能不断增加。