【原创&交流】Comamnd模式和Factory模式在一次代码重构中的应用
如何应用设计模式,是一个见仁见智的问题,可能也没有一定之规。以我的水平也谈得不一定好。前段时间重构了公司软件中的二维图形交互方面的代码,总结了一些经验供大家分享,期待起一个抛砖引玉的作用。
该软件是基于MFC界面框架开发的。MFC的Doc-View架构本质上是一种MVC架构。随着软件功能开发越来越多,图形的二维显示及各种浏览命令、编辑命令的实现集中在视图类(即View)。视图类的代码越来用臃肿(将近上万行的代码),它的维护更新和升级以后都将大成问题。一个例证就是在各种键盘鼠标消息响应函数写无数的case分支语句来处理各种命令,类似于:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!m_bActive)
return;
CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
if (pTool != NULL)
pTool->OnLButtonDown(this, nFlags, point);
}
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
if (!m_bActive)
return;
CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
if (pTool != NULL)
pTool->OnLButtonUp(this, nFlags, point);
}
void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bActive)
return;
CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
if (pTool != NULL)
pTool->OnMouseMove(this, nFlags, point);
}
// 图形类型枚举变量
enum DrawShape
{
selection,
line,
rect,
roundRect,
ellipse,
poly
};
// 绘制工具基类
class CDrawTool
{
// Constructors
public:
CDrawTool(DrawShape nDrawShape);
// Overridables
virtual void OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnEditProperties(CDrawView* pView);
virtual void OnCancel();
// Attributes
DrawShape m_drawShape;
static CDrawTool* FindTool(DrawShape drawShape);
static CPtrList c_tools;
static CPoint c_down;
static UINT c_nDownFlags;
static CPoint c_last;
static DrawShape c_drawShape;
};
// 绘制矩形类
class CRectTool : public CDrawTool
{
// Constructors
public:
CRectTool(DrawShape drawShape);
// Implementation
virtual void OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point);
virtual void OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point);
};
CDrawTool* CDrawTool::FindTool(DrawShape drawShape)
{
POSITION pos = c_tools.GetHeadPosition();
while (pos != NULL)
{
CDrawTool* pTool = (CDrawTool*)c_tools.GetNext(pos);
if (pTool->m_drawShape == drawShape)
return pTool;
}
return NULL;
}
enum cmd_type
{
Cmd_NoOpertin, // 无操作
Cmd_ViewAll, // 全图显示
…
};
// 命令类基类
class CBaseComand
{
public:
CBaseComand(CMyView *pView);
virtual ~ CBaseComand();
virtual void Execute(); // 外部调用方法
//
private:
CMyView *pView; // 保存视图类指针,方便访问视图类的数据
}
class CViewAllCmd : public CBaseComand
{
public:
CViewAllCmd(CMyView *pView);
virtual ~ CViewAllCmd ();
void Execute(); // 外部调用方法
//
private:
CMyView *pView; // 保存视图类指针,方便访问视图类的数据
}