通常,我们对class 的定义为一个可以抽象的实物,就像书上说的那个什么人呀,车呀 ,其实这是对class 的一个片面的理解。
然后我们再来看看对class 的定义:数据与数据操作的一个集合体。
从这个定义中我们不难看出有两个关键的东西,一是数据,一是动作。而我们通常强调的是数据为主体,以动作为辅的一种class结构。其实在很多情况下,以动作为主往往比以数据为主要清晰的多。
说一个很简单的类子
Undo & Redo
在我们编写一个程序的时候,这个功能往往是少不了的,随着功能的复杂,那么Undo Redo也会变得很难控制,这里我就利用以动作为主设计一套比较合理的Undo Redo 机制
Undo & Redo 基类
class CAction : public CObject
{
public:
CAction(BOOL inAlreadyDone = false,
const CString& strRedoString = "",
const CString& strUndoString = "");
virtual ~CAction();
virtual void Finalize();
virtual void Redo(); // Also functions as "Do"
virtual void Undo();
BOOL IsDone() const { return m_IsDone; };
virtual BOOL IsPostable() const;
virtual BOOL CanRedo() const;
virtual BOOL CanUndo() const;
virtual void GetDescription(
CString& strRedoString,
CString& strUndoString) const;
protected:
CString m_strRedoString;
CString m_strUndoString;
BOOL m_IsDone; // Is Action done or redone?
// Pure Virtual functions. Subclasses must override!
virtual void RedoSelf() = 0;
virtual void UndoSelf() = 0;
};
从基类派生出来到一个Undo 动子
class CZoomAction : public CAction
{
public:
CZoomAction(CDrawPicView * pView,float nFactor);
virtual ~CZoomAction();
protected:
CDrawPicView* m_pView;
float m_nOld;
float m_nNew;
protected:
virtual void RedoSelf() ;
virtual void UndoSelf() ;
};
管理整个Undo Redo 系统
class CUndoer
{
public:
void AddAction(CAction * pAction);
BOOL GetUndoStatus()const;
BOOL GetRedoStatus()const;
void Redo();
void Undo();
CUndoer();
virtual ~CUndoer();
protected:
CObList* m_pActionList;
int m_nCurrentUndoIndex;
int m_nCurrentRedoIndex;
};
当一个动作发生的时候
CZoomAction * pZoom = new CZoomAction(this,nFact);
m_Undoer.AddAction(pZoom);
当需要Undo 的时候
m_Undoer.Undo();
当控制menu 状态的时候
pCmdUI->Enable(m_Undoer.GetRedoStatus());
pCmdUI->Enable(m_Undoer.GetUndoStatus());
这样,如果你的那个window需要实现Undo & Redo 那么只需要包含CUndoer 的一个对象,
然后就是针对每个需要Undo & Redo 的动作从CAction 派生出一个类,这个类将包含这个Action所需要的相关数据,并且同时实现 Undo Redo 的具体动作,如果中间有临时申请内存变量,可以在这个CAction 析构的时候释放。
这样设计的好处是:
将动作独立出来形成一个class
将Redo and Undo 放在同一个class中,比较清楚
减轻Window 的负担(将大部分动作全部封装到对应的Action class 中,windows 本事就只需要负责一些UI 上的动作)
可以集中管理Redo and Undo