前不久看了 敏捷軟件開發 原則、模式與實踐,有點想法,所以就把我以前寫得一個RedoUndo的框架改了一下,成了下面的情況。
我將操作RedoUndo的模塊的接口獨立了出來,這樣在將來的擴展上就不會有太大的困難,并且將他獨立與顯示模塊很大程度上避免了耦合。
在使用的時候可以有選擇的使用RedoUndo的功能,如果某個工具需要RedoUndo的功能則直接繼承與TransactionCommand即可。這樣避免了冗余,在一些工具中不用承擔一些不需要的永遠不會用到的方法。
RedoUndo模塊是使用標準的C++寫的,為了測試這個模塊我使用了Qt庫,用于圖形顯示,這樣產生了一個新的模塊DrawTransaction。
這是顯示模塊,在這里只顯示接口
我將操作RedoUndo的模塊的接口獨立了出來,這樣在將來的擴展上就不會有太大的困難,并且將他獨立與顯示模塊很大程度上避免了耦合。
在使用的時候可以有選擇的使用RedoUndo的功能,如果某個工具需要RedoUndo的功能則直接繼承與TransactionCommand即可。這樣避免了冗余,在一些工具中不用承擔一些不需要的永遠不會用到的方法。
RedoUndo模塊是使用標準的C++寫的,為了測試這個模塊我使用了Qt庫,用于圖形顯示,這樣產生了一個新的模塊DrawTransaction。
1
/**//***********************************************************************
2
* \file TransactionCommand.h
3
* \date 2008-07-06
4
* \author HYin
5
**********************************************************************/
6
7
#ifndef TRANSACTIONCOMMAND_H
8
#define TRANSACTIONCOMMAND_H
9
10
namespace hy
11

{
12
class TransactionCommand
13
{
14
public :
15
TransactionCommand();
16
virtual ~TransactionCommand();
17
18
virtual bool redo() = 0;
19
virtual bool undo() = 0;
20
21
};
22
}
23
24
#endif
25


2

3

4

5

6

7

8

9

10

11



12

13



14

15

16

17

18

19

20

21

22

23

24

25

1
/**//***********************************************************************
2
* \file RedoUndo.h
3
* \date 2008-07-06
4
* \author HYin
5
**********************************************************************/
6
7
#ifndef REDOUNDOTOOL_H
8
#define REDOUNDOTOOL_H
9
10
// ---------------------------------------------------------------------------------------------------------------
11
#include "TransactionCommand.h"
12
#include <vector>
13
// ---------------------------------------------------------------------------------------------------------------
14
15
namespace hy
16

{
17
class TransactionCommand;
18
19
class RedoUndoTool : public TransactionCommand
20
{
21
typedef TransactionCommand Command;
22
public :
23
explicit RedoUndoTool( int depth = 10 );
24
25
void setDepth( int depth )
26
{ m_iRedoUndoDepth = depth; }
27
28
void add( Command * command );
29
30
void clear()
31
{ m_aCommandStack.clear(); }
32
33
virtual bool redo();
34
virtual bool undo();
35
36
private :
37
// depth for undo transaction 
38
int m_iRedoUndoDepth;
39
40
// current step 
41
int m_iCurrentStep;
42
43
// Command stack to store 
44
std::vector< Command * > m_aCommandStack;
45
46
};
47
48
}
49
50
#endif
51


2

3

4

5

6

7

8

9

10

11

12

13

14

15

16



17

18

19

20



21

22

23

24

25

26



27

28

29

30

31



32

33

34

35

36

37


38

39

40


41

42

43


44

45

46

47

48

49

50

51

1
/**//***********************************************************************
2
* \file RedoUndo.cpp
3
* \date 2008-07-06
4
* \author HYin
5
**********************************************************************/
6
7
// ---------------------------------------------------------------------------------------------------------------
8
#include "RedoUndoTool.h"
9
#include <iostream>
10
#include <assert.h>
11
using namespace std;
12
// ---------------------------------------------------------------------------------------------------------------
13
14
// ---------------------------------------------------------------------------------------------------------------
15
#define hy_assert_error(str) { std::cerr << str << endl; assert(false); }
16
#define hy_assert_warning(str) { std::cout << str << endl; }
17
// ---------------------------------------------------------------------------------------------------------------
18
19
namespace hy
20

{
21
RedoUndoTool::RedoUndoTool( int depth )
22
: m_iRedoUndoDepth(depth), m_iCurrentStep(-1)
23
{
24
m_aCommandStack.clear();
25
}
26
27
void RedoUndoTool::add( RedoUndoTool::Command * command )
28
{
29
int num = m_aCommandStack.size();
30
31
if ( m_iCurrentStep == num-1 || m_iCurrentStep == -1 )
32
{
33
m_aCommandStack.push_back(command);
34
m_iCurrentStep ++;
35
}
36
else if ( m_iCurrentStep < num-1 )
37
{
38
m_aCommandStack.erase(
39
m_aCommandStack.begin()+m_iCurrentStep+1, m_aCommandStack.end()
40
);
41
m_aCommandStack.push_back(command);
42
m_iCurrentStep ++;
43
}
44
else
45
{
46
hy_assert_error( " error : RedoUndoTool::add( const RedoUndoTool::Command & command ) :"
47
<< " invalid m_iCurrentStep" );
48
}
49
50
// keep the depth 
51
num = m_aCommandStack.size();
52
if ( num > m_iRedoUndoDepth )
53
{
54
m_aCommandStack.erase( m_aCommandStack.begin(),
55
m_aCommandStack.begin()+num-m_iRedoUndoDepth );
56
m_iCurrentStep = m_iRedoUndoDepth-1;
57
}
58
}
59
60
bool RedoUndoTool::redo()
61
{
62
int num = m_aCommandStack.size();
63
if ( m_iCurrentStep == num-1 )
64
{
65
hy_assert_warning(" warning : RedoUndoTool::redo() :"
66
<< " out of range: default to return directively!! " );
67
}
68
else if ( m_iCurrentStep < num-1 && m_iCurrentStep >= -1 )
69
{
70
return m_aCommandStack[++m_iCurrentStep]->redo();
71
}
72
else
73
{
74
hy_assert_error(" error : RedoUndoTool::redo() :"
75
<< " invalid m_iCurrentStep" );
76
}
77
return false;
78
}
79
80
bool RedoUndoTool::undo()
81
{
82
int num = m_aCommandStack.size();
83
if ( m_iCurrentStep == -1 )
84
{
85
hy_assert_warning(" warning : RedoUndoTool::undo() :"
86
<< " out of range: default to return directively!! " );
87
}
88
else if ( m_iCurrentStep <= num-1 && m_iCurrentStep > -1 )
89
{
90
return m_aCommandStack[m_iCurrentStep--]->undo();
91
}
92
else
93
{
94
hy_assert_error(" error : RedoUndoTool::undo() :"
95
<< " invalid m_iCurrentStep" );
96
}
97
return false;
98
}
99
100
}
101


2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20



21

22

23



24

25

26

27

28



29

30

31

32



33

34

35

36

37



38

39

40

41

42

43

44

45



46

47

48

49

50


51

52

53



54

55

56

57

58

59

60

61



62

63

64



65

66

67

68

69



70

71

72

73



74

75

76

77

78

79

80

81



82

83

84



85

86

87

88

89



90

91

92

93



94

95

96

97

98

99

100

101

這是顯示模塊,在這里只顯示接口
1
/**//***********************************************************************
2
* \file DrawTransaction.h
3
* \date 2008-07-07
4
* \author HYin
5
**********************************************************************/
6
7
#ifndef DRAWTRANSACTION_H
8
#define DRAWTRANSACTION_H
9
10
// ---------------------------------------------------------------------------------------------------------------
11
// ---------------------------------------------------------------------------------------------------------------
12
13
namespace hy
14

{
15
class DrawTransaction
16
{
17
public :
18
DrawTransaction();
19
virtual ~DrawTransaction();
20
21
virtual void draw() =0;
22
};
23
}
24
25
#endif
26


2

3

4

5

6

7

8

9

10

11

12

13

14



15

16



17

18

19

20

21

22

23

24

25

26
