-
Notifications
You must be signed in to change notification settings - Fork 80
/
G21_Command.cpp
160 lines (117 loc) · 3.74 KB
/
G21_Command.cpp
1
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/**************************************************************************************************
*
* \file G21_Command.cpp
* \brief Guideline 21: Use Commands to Isolate What Things are Done
*
* Copyright (C) 2022 Klaus Iglberger - All Rights Reserved
*
* This file is part of the supplemental material for the O'Reilly book "C++ Software Design"
* (https://www.oreilly.com/library/view/c-software-design/9781098113155/).
*
**************************************************************************************************/
//---- <CalculatorCommand.h> ----------------------------------------------------------------------
class CalculatorCommand
{
public:
virtual ~CalculatorCommand() = default;
virtual int execute( int i ) const = 0;
virtual int undo( int i ) const = 0;
};
//---- <Add.h> ------------------------------------------------------------------------------------
//#include <CalculatorCommand.h>
class Add : public CalculatorCommand
{
public:
explicit Add( int operand ) : operand_(operand) {}
int execute( int i ) const override
{
return i + operand_;
}
int undo( int i ) const override
{
return i - operand_;
}
private:
int operand_{};
};
//---- <Subtract.h> -------------------------------------------------------------------------------
//#include <CalculatorCommand.h>
class Subtract : public CalculatorCommand
{
public:
explicit Subtract( int operand ) : operand_(operand) {}
int execute( int i ) const override
{
return i - operand_;
}
int undo( int i ) const override
{
return i + operand_;
}
private:
int operand_{};
};
//---- <Calculator.h> -----------------------------------------------------------------------------
//#include <CalculatorCommand.h>
#include <memory>
#include <stack>
class Calculator
{
public:
void compute( std::unique_ptr<CalculatorCommand> command );
void undoLast();
int result() const;
void clear();
private:
using CommandStack = std::stack<std::unique_ptr<CalculatorCommand>>;
int current_{};
CommandStack stack_;
};
//---- <Calculator.cpp> ----------------
//#include <Calculator.h>
#include <utility>
void Calculator::compute( std::unique_ptr<CalculatorCommand> command )
{
current_ = command->execute( current_ );
stack_.push( std::move(command) );
}
void Calculator::undoLast()
{
if( stack_.empty() ) return;
auto command = std::move(stack_.top());
stack_.pop();
current_ = command->undo(current_);
}
int Calculator::result() const
{
return current_;
}
void Calculator::clear()
{
current_ = 0;
CommandStack{}.swap( stack_ ); // Clearing the stack
}
//---- <Main.cpp> ---------------------------------------------------------------------------------
//#include <Calculator.h>
//#include <Add.h>
//#include <Subtract.h>
#include <cstdlib>
#include <memory>
#include <utility>
int main()
{
Calculator calculator{};
auto op1 = std::make_unique<Add>( 3 );
auto op2 = std::make_unique<Add>( 7 );
auto op3 = std::make_unique<Subtract>( 4 );
auto op4 = std::make_unique<Subtract>( 2 );
calculator.compute( std::move(op1) ); // Computes 0 + 3, stores and returns 3
calculator.compute( std::move(op2) ); // Computes 3 + 7, stores and returns 10
calculator.compute( std::move(op3) ); // Computes 10 - 4, stores and returns 6
calculator.compute( std::move(op4) ); // Computes 6 - 2, stores and returns 4
calculator.undoLast(); // Reverts the last operation,
// stores and returns 6
int const res = calculator.result(); // Get the final result: 6
// ...
return EXIT_SUCCESS;
}