组合而不是继承,单一职责
今天在写C++程序的时候,有一个使用了三年多的模型,大概是这样的:
有一个界面捕获需要主窗口的鼠标事件的时候,那么他就需要从IMouseEvent继承接口,然后像RegisterEvent(IMouseEvent *event)注册,如果有鼠标事件,主窗口会通过调用虚函数来通知这个界面
我们一般的代码是这样的:
class MyUI:public IMouseEvent
{
virtual void OnMouseEvent( MouseEvent &event );
virtual void OnMouseLeftDown( MouseEvent &event);
virtual void OnMouseRightDown(MouseEvent &evnet)
Other UI Process Function
......
}
MyUI *ui = new MyUI();
MainUI->RegisterEvent( ui );
这样有两个坏处:
1.把事件处理机制混合在窗口里面了,随着代码的增加,鼠标模式的处理会更加复杂,这点在现在的维护上已经体现出来了
2.MyUI不得不依赖IMouseEvent接口
想起来上次面试的时候,对方问我设计模式的问题,我一直不是很注重设计模式,可能跟我的工作有关,我更多的是在处理逻辑而不是设计,所以那次回来后我一直在想,我们的代码写得越久越难维护是不是跟我不注重设计模式有关,设计模式有一个单一原则,能否把鼠标处理事件移动出去,这样就变成
class MyUIMouseEvent:public IMouseEvent
{
MyUIMouseEvent(MyUI *UI);
virtual void OnMouseEvent( MouseEvent &event );
virtual void OnMouseLeftDown( MouseEvent &event);
virtual void OnMouseRightDown(MouseEvent &evnet)
......
}
然后利用组合
class MyUI
{
public:
MyUIMouseEvent *m_MouseEvent;
friend class MyUIMouseEvent;
}
这样的话,鼠标事件对界面所进行的逻辑处理会在MyUIMouseEvent里面处理,看起来起码比以前更清爽多了,也实现了单一职责(虽然我不知道这个是不是)
但是这样的话MyUIMouseEvent还是必须依赖于IMouseEvent,因为开发环境已经切换到vs2010了,开始支持bind和function系列函数了,通过这两个函数,我们可以利用function和bind取代虚函数,而且减少头文件依赖
比如在.h里面
class MyUIMouseEvent
{
MyUIMouseEvent(MyUI *UI);
void OnMouseEvent( MouseEvent &event );
void OnMouseLeftDown( MouseEvent &event);
void OnMouseRightDown(MouseEvent &evnet)
}
MyUIMouseEvent的头文件不会产生任何的依赖,而是在cpp里面通过bind和function绑定,然后提供新的RegisterEvent接口专门注册这一些列函数,三个头文件没有产生任何的依赖,比之前好多了
因为程序已经变得很大了,经常改动一个头文件的东西,一大堆的文件都要重新编译,所以最近越来越注意如何减少头文件依赖