Skip to content

Commit 3a87ccf

Browse files
xiao chengxiao cheng
xiao cheng
authored and
xiao cheng
committed
add a few new patterns
1 parent b3b23b5 commit 3a87ccf

21 files changed

+1556
-1
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"name": "(lldb) Launch",
99
"type": "cppdbg",
1010
"request": "launch",
11-
"program": "${workspaceFolder}/bin/cpp11_threadsafe_queue",
11+
"program": "${workspaceFolder}/bin/Interpreter",
1212
"args": [],
1313
"stopAtEntry": false,
1414
"cwd": "${workspaceFolder}",

CMakeLists.txt

+6
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,10 @@ if(Boost_FOUND)
2525
add_subdirectory(Composite)
2626
add_subdirectory(Delegation)
2727
add_subdirectory(Facade)
28+
add_subdirectory(Flyweight)
29+
add_subdirectory(Proxy)
30+
add_subdirectory(ChainOfRes)
31+
add_subdirectory(CommandPattern)
32+
add_subdirectory(Interpreter)
33+
add_subdirectory(IteratorPattern)
2834
endif()

ChainOfRes/CMakeLists.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
3+
project(COR1)
4+
5+
include_directories(${Boost_INCLUDE_DIRS})
6+
7+
add_executable(${PROJECT_NAME} main.cpp)
8+
9+
target_link_libraries(${PROJECT_NAME} PUBLIC
10+
gtest_main
11+
${Boost_LIBRARIES}
12+
)
13+
14+
add_test(
15+
NAME ${PROJECT_NAME}
16+
COMMAND ${PROJECT_NAME}
17+
)
18+
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ../bin)

ChainOfRes/main.cpp

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <ctime>
4+
using namespace std;
5+
6+
class Base
7+
{
8+
Base *next; // 1. "next" pointer in the base class
9+
public:
10+
Base()
11+
{
12+
next = 0;
13+
}
14+
void setNext(Base *n)
15+
{
16+
next = n;
17+
}
18+
void add(Base *n)
19+
{
20+
if (next)
21+
next->add(n);
22+
else
23+
next = n;
24+
}
25+
// 2. The "chain" method in the base class always delegates to the next obj
26+
virtual void handle(int i)
27+
{
28+
next->handle(i);
29+
}
30+
};
31+
32+
class Handler1 : public Base
33+
{
34+
public:
35+
/*virtual*/ void handle(int i)
36+
{
37+
if (rand() % 3)
38+
{
39+
// 3. Don't handle requests 3 times out of 4
40+
cout << "H1 passed " << i << " ";
41+
Base::handle(i); // 3. Delegate to the base class
42+
}
43+
else
44+
cout << "H1 handled " << i << " ";
45+
}
46+
};
47+
48+
class Handler2 : public Base
49+
{
50+
public:
51+
/*virtual*/ void handle(int i)
52+
{
53+
if (rand() % 3)
54+
{
55+
cout << "H2 passed " << i << " ";
56+
Base::handle(i);
57+
}
58+
else
59+
cout << "H2 handled " << i << " ";
60+
}
61+
};
62+
63+
class Handler3 : public Base
64+
{
65+
public:
66+
/*virtual*/ void handle(int i)
67+
{
68+
if (rand() % 3)
69+
{
70+
cout << "H3 passed " << i << " ";
71+
Base::handle(i);
72+
}
73+
else
74+
cout << "H3 handled " << i << " ";
75+
}
76+
};
77+
78+
int main()
79+
{
80+
srand(time(0));
81+
Handler1 root;
82+
Handler2 two;
83+
Handler3 thr;
84+
root.add(&two);
85+
root.add(&thr);
86+
thr.setNext(&root);
87+
for (int i = 1; i < 10; i++)
88+
{
89+
root.handle(i);
90+
cout << '\n';
91+
}
92+
}

CommandPattern/CMakeLists.txt

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
3+
project(CommandPattern)
4+
5+
include_directories(${Boost_INCLUDE_DIRS})
6+
7+
add_executable(simple_commands simple_commands.cpp)
8+
add_executable(macro_commands macro_commands.cpp)
9+
10+
target_link_libraries(simple_commands PUBLIC gtest_main ${Boost_LIBRARIES})
11+
target_link_libraries(macro_commands PUBLIC gtest_main ${Boost_LIBRARIES})
12+
13+
install(TARGETS simple_commands macro_commands RUNTIME DESTINATION ../bin)
14+
15+

CommandPattern/bank_command.cpp

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <vector>
4+
using namespace std;
5+
6+
struct BankAccount
7+
{
8+
int balance = 0;
9+
int overdraft_limit = -500;
10+
11+
void deposit(int amount)
12+
{
13+
balance += amount;
14+
cout << "deposited " << amount << ", balance now " << balance << "\n";
15+
}
16+
17+
void withdraw(int amount)
18+
{
19+
if (balance - amount >= overdraft_limit)
20+
{
21+
balance -= amount;
22+
cout << "withdrew " << amount << ", balance now " << balance << "\n";
23+
}
24+
}
25+
};
26+
27+
struct Command
28+
{
29+
virtual ~Command() = default;
30+
virtual void call() const = 0;
31+
virtual void undo() const = 0;
32+
};
33+
34+
// should really be BankAccountCommand
35+
struct BankAccountCommand : Command
36+
{
37+
BankAccount &account;
38+
enum Action
39+
{
40+
deposit,
41+
withdraw
42+
} action;
43+
int amount;
44+
45+
BankAccountCommand(BankAccount &account,
46+
const Action action, const int amount)
47+
: account(account), action(action), amount(amount) {}
48+
49+
void call() const override
50+
{
51+
switch (action)
52+
{
53+
case deposit:
54+
account.deposit(amount);
55+
break;
56+
case withdraw:
57+
account.withdraw(amount);
58+
break;
59+
default:
60+
break;
61+
}
62+
}
63+
64+
void undo() const override
65+
{
66+
switch (action)
67+
{
68+
case withdraw:
69+
account.deposit(amount);
70+
break;
71+
case deposit:
72+
account.withdraw(amount);
73+
break;
74+
default:
75+
break;
76+
}
77+
}
78+
};
79+
80+
// vector doesn't have virtual dtor, but who cares?
81+
struct CompositeBankAccountCommand
82+
: vector<BankAccountCommand>,
83+
Command
84+
{
85+
CompositeBankAccountCommand(const initializer_list<value_type> &items)
86+
: vector<BankAccountCommand>(items) {}
87+
88+
void call() const override
89+
{
90+
for (auto &cmd : *this)
91+
cmd.call();
92+
}
93+
94+
void undo() const override
95+
{
96+
for (auto &cmd : *this)
97+
cmd.undo();
98+
}
99+
};
100+
101+
int main()
102+
{
103+
BankAccount ba;
104+
/*vector<BankAccountCommand> commands{*/
105+
CompositeBankAccountCommand commands{
106+
BankAccountCommand{ba, BankAccountCommand::deposit, 100},
107+
BankAccountCommand{ba, BankAccountCommand::withdraw, 200}};
108+
109+
cout << ba.balance << endl;
110+
111+
// apply all the commands
112+
/*for (auto& cmd : commands)
113+
{
114+
cmd.call();
115+
}*/
116+
commands.call();
117+
118+
cout << ba.balance << endl;
119+
120+
/*for_each(commands.rbegin(), commands.rend(),
121+
[](const BankAccountCommand& cmd) { cmd.undo(); });*/
122+
commands.undo();
123+
124+
cout << ba.balance << endl;
125+
126+
getchar();
127+
return 0;
128+
}

CommandPattern/command_test.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#include <iostream>
2+
#include <vector>
3+
using namespace std;
4+
5+
struct Command
6+
{
7+
enum Action
8+
{
9+
deposit,
10+
withdraw
11+
} action;
12+
int amount{0};
13+
bool success{false};
14+
};
15+
16+
struct Account
17+
{
18+
int balance{0};
19+
20+
void process(Command &cmd)
21+
{
22+
switch (cmd.action)
23+
{
24+
case Command::deposit:
25+
balance += cmd.amount;
26+
cmd.success = true;
27+
break;
28+
case Command::withdraw:
29+
cmd.success = (balance >= cmd.amount);
30+
if (cmd.success)
31+
balance -= cmd.amount;
32+
break;
33+
}
34+
}
35+
};
36+
37+
#include "gtest/gtest.h"
38+
39+
//#include "helpers/iohelper.h"
40+
41+
//#include "exercise.cpp"
42+
43+
namespace
44+
{
45+
class Evaluate : public testing::Test
46+
{
47+
public:
48+
};
49+
50+
TEST_F(Evaluate, LotsOfAccountTests)
51+
{
52+
Account a;
53+
Command command{Command::deposit, 100};
54+
a.process(command);
55+
56+
ASSERT_EQ(100, a.balance);
57+
ASSERT_TRUE(command.success);
58+
59+
command = Command{Command::withdraw, 50};
60+
a.process(command);
61+
62+
ASSERT_EQ(50, a.balance);
63+
ASSERT_TRUE(command.success);
64+
65+
command = Command{Command::withdraw, 150};
66+
a.process(command);
67+
68+
ASSERT_EQ(50, a.balance);
69+
ASSERT_FALSE(command.success);
70+
}
71+
} // namespace
72+
73+
int main(int ac, char *av[])
74+
{
75+
testing::InitGoogleTest(&ac, av);
76+
return RUN_ALL_TESTS();
77+
}

0 commit comments

Comments
 (0)