您的位置:首页 > 其它

软件设计模式与原则

2014-03-19 16:57 204 查看

第九章 设计模式与原则

软件设计模式(Designpattern)是一套被反复使用的代码设计经验总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。好的设计,成就好的作品。但在软件设计的过程中,若有一些设计原则(Design Principle)的约束,那我们的软件会重构得更好。设计模式和设计原则博大精深,需要我们长时间的实践和总结才能真正领悟到其真谛,本章首先以“观察者模式”为例,介绍设计模式在Windows Forms中的应用(其他常用设计模式略),之后详细介绍五大设计原则(简称Solid原则)。

9.1软件的设计模式

9.1.1观察者模式

程序的运行意味着模块与模块之间、对象与对象之间不停地有数据交换,观察者模式强调的就是,当一个目标本身的状态发生改变时(或者满足某一条件),它会主动发出通知,通知对该变化感兴趣的其他对象,如果将通知者称为“Subject”(主体),将被通知者称为“Observer”(观察者),具体结构图如下:



图9-1 观察者模式中类关系图
如上图9-1所示,图中将主体和观察者的逻辑抽象出来两个接口,分别为:ISubject和IObserver,ISubject接口中包含一个通知观察者的NotifyObservers方法、一个添加观察者的AddObserver方法和一个RemoveObserver方法,IObserver接口中则只包含一个接受通知的Notify方法,ISubject和IObserver接口的关系为:一对多,一个主体可以通知多个观察者。
具体代码实现如下:

//Code 9-1
interface ISubject  //NO.1
{
voidNotifyObservers(string msg);
voidAddObserver(IObserver observer);
voidRemoveObserver(IObserver observer);
}
interface IObserver  //NO.2
{
voidNotify(string msg);
}
class MySubject:ISubject
{
//…
ArrayList_observers_list = new ArrayList();
publicvoid AddObserver(IObserver observer) //NO.3
{
if(!_observers_list.Contains(observer))
{
_observers_list.Add(observer);
}
}
publicvoid RemoveObserver(IObserver observer) //NO.4
{
if(_observers_list.Contains(observer))
{
_observers_list.Remove(observer);
}
}
publicvoid NotifyObservers(string msg)  //NO.5
{
foreach(IObserverobserver in _observers_list)
{
observer.Notify(msg);
}
}
publicvoid DoSomething()
{
//…
if(…)  //NO.6
{
NotifyObservers(…);
}
}
}
class MyObserver:IObserver
{
publicvoid Notify(string msg)
{
Console.WriteLine(“receivemsg :” + msg);  //NO.7
}
}
class YourObserver:IObserver
{
publicvoid Notify(string msg)
{
//sendemail to others  NO.8
}
}


如上代码Code 9-1中所示,NO.1和NO.2处分别定义了ISubject和IObserver接口,接着定义了一个具体的主体类MySubject,该类实现了ISubject接口,在AddObserver、RemoveObserver分别将观察者加入或者移除集合_observers_list(NO.3和NO.4处),最后在NotifyObservers方法中,遍历_observers_list集合,将通知发送到每个观察者(NO.5处),注意我们可以在DoSomething方法中当满足某一条件时,通知观察者(NO.6处)。我们使用IObserver接口定义了两个具体的观察者MyObserver和YourObserver,在两者的Notify方法中分别按照自己的逻辑去处理通知信息(一个直接将msg打印出来,一个将msg以邮件形式发送给别人)(NO.7和NO.8处)。

现在我们可以将MySubject类对象当作一个具体的主体,将MyObserver类对象和YourObserver类对象当做具体的观察者,那么代码中可以这样去使用:

//Code 9-2
ISubject subject = new MySubject();
subject.AddObserver(new MyObserver());  //NO.1
subject.AddObserver(new YourObserver());   //NO.2

subject.NotifyObservers(“it's a test!”);  //NO.3
(subject as MySubject).DoSomething();  //NO.4


如上代码Code 9-2所示,我们向主体subject中添加两个观察者(NO.1和NO.2处),之后使用ISubject.NotifyObservers方法通知观察者(NO.3),另外,我们还可以使用MySubject.DoSomething方法去通知观察者(当某一条件满足时),两个观察者分别会做不同的处理,一个直接将“it's a test”字符串打印输出,而另一个则将字符串以邮件的形式发送给别人。

注:Code 9-2中,我们不能使用ISubject接口去调用DoSomething方法,而必须先将ISubject类型转换成MySubject类型,因为DoSomething不属于ISubject接口。

观察者模式中,整个流程见下图9-2:



图9-2 观察者模式中的运行流程
如上图9-2所示,在有些情况中,NO.2处会做一些筛选,换句话说,主体有可能根据条件通知部分观察者,NO.4处虚线框表示可选,如果主体关心观察者的处理结果,那么观察者就应该将自己的处理结果返回给主体。“观察者模式”是所有框架使用得最频繁的设计模式之一,原因很简单,“观察者模式”分隔开了框架代码和框架使用者编写的代码,它是“好莱坞原则”(Hollywood Principle,don't call us,we will call you)的具体实现手段,而“好莱坞原则”是所有框架都严格遵守的。
Windows Forms框架中的“观察者模式”主要不是通过“接口-具体”这种方式去实现的,更多的是使用.NET中的“委托-事件”去实现,详见下一小节。

9.1.2Windows Forms中的观察者模式

在WindowsForms框架中,可以说“观察者模式”无处不在,在第四章讲Winform程序结构时已经有所说明,比如控件处理Windows消息时,最终是以“事件”的形式去通知事件注册者的,那么这里的事件注册者就是观察者模式中的“观察者”,控件就是观察者模式中的“主体”。我们回忆一下第四章中有关System.Windows.Forms.Control类的代码(部分):

//Code 9-3
class Control:Component
{
//…
publicevent EventHandler Event1;
publicevent EventHandler Event2;
protectedvirtual void WndProc(ref Message m)
{
switch(m.Msg)
{
case1:  //NO.1
{
//…
OnEvent1(…);
break;
}
case2:  //NO.2
{
OnEvent2(…);
break;
}
//…
}
}
protectedvirtual void OnEvent1(EventArgs e)
{
if(Event1!= null)
{
Event1(this,e);//NO.3
}
}
protectedvirtual void OnEvent2(EventArgs e)
{
if(Event2!= null)
{
Event2(this,e);  //NO.4
}
}
}


如上代码Code 9-3所示,在Control类的WndProc窗口过程中的switch/case块中,会根据不同的Windows消息去激发不同的事件(NO.1和NO.2处),由于WndProc是一个虚方法,所有在任何一个Control的派生类中,均可以重写WndProc虚方法,处理Windows消息,然后以“事件”的形式去通知事件注册者。

如果我们在Form1中注册了一个Button类对象btn1的Click事件,那么btn1就是观察者模式中的“主体”,Form1(的实例)就是观察者模式中的“观察者”,如下代码:

//Code 9-4
class Form1:Form
{
//…
publicForm1()
{
InitializeComponent();
btn1.Click+= new EventHandler(btn1_Click);  //NO.1
}
privatevoid btn1_Click(object sender,EventArgs e) //NO.2
{
//…
}
}


如上图Code 9-4代码所示,我们在Form1的构造方法中注册了btn1的Click事件(NO.1处),那么btn1就是“主体”,Form1(的实例)就是“观察者”,当btn1需要处理Windows消息时,就会激发事件,通知Form1(的实例)。

WindowsForms框架正是使用“观察者模式”实现了框架代码与框架使用者编写的代码相分离。

注:我们可以认为,事件的发布者等于观察者模式中的“主体”(Subject),而事件的注册者等于观察者模式中的“观察者”,有关“事件编程”,请参考第六章。

未完待续

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: