Design Pattern Examples
Overview of object-oriented design patterns
NullObject_Exercise.c
Go to the documentation of this file.
1
6
7#include <ctype.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
14#include "NullObject_Exercise.h"
15
16
20static void MoveCommand_Show(char commandToken, const char *commandName)
21{
22 if (commandName != NULL)
23 {
24 printf(" '%c' -> %s\n", commandToken, commandName);
25 }
26}
27
28
32static void MoveCommandLeft_Execute(void)
33{
34 printf("move left");
35}
36
37
41static void MoveCommandRight_Execute(void)
42{
43 printf("move right");
44}
45
46
50static void MoveCommandUp_Execute(void)
51{
52 printf("move up");
53}
54
55
59static void MoveCommandDown_Execute(void)
60{
61 printf("move down");
62}
63
64
69static void MoveCommandNone_Execute(void)
70{
71 // Do nothing.
72}
73
74
88
104static bool _MoveProcessor_ParseMoves(const char *moveList, MoveCommandList *commandList)
105{
106 bool parsed = false;
107
108 if (moveList != NULL && commandList != NULL)
109 {
110 parsed = true;
111 size_t moveListSize = strlen(moveList);
112 for (size_t index = 0; index < moveListSize; index++)
113 {
114 char commandChar = (char)toupper(moveList[index]);
115 MoveCommand* moveCommand = NULL;
116
117 switch (commandChar)
118 {
119 case 'U':
120 moveCommand = MoveCommand_Create(commandChar, "Up", MoveCommandUp_Execute);
121 break;
122
123 case 'D':
124 moveCommand = MoveCommand_Create(commandChar, "Down", MoveCommandDown_Execute);
125 break;
126
127 case 'L':
128 moveCommand = MoveCommand_Create(commandChar, "Left", MoveCommandLeft_Execute);
129 break;
130
131 case 'R':
132 moveCommand = MoveCommand_Create(commandChar, "Right", MoveCommandRight_Execute);
133 break;
134
135 default:
136 // Everything else is a "do nothing" command.
137 moveCommand = MoveCommand_Create(commandChar, "None", MoveCommandNone_Execute);
138 break;
139 }
140 if (moveCommand != NULL)
141 {
142 if (!MoveCommandList_Add(commandList, moveCommand))
143 {
144 printf(" Error! Out of memory condition adding command %c.\n", commandChar);
145 MoveCommandList_Clear(commandList);
146 parsed = false;
147 break;
148 }
149 }
150 else
151 {
152 printf(" Error! Out of memory condition creating MoveCommand for command %c.\n", commandChar);
153 parsed = false;
154 break;
155 }
156 }
157 }
158
159 return parsed;
160}
161
162
175{
176 if (commands != NULL)
177 {
178 for (size_t index = 0; index < commands->commands_count; index++)
179 {
180 MoveCommand* moveCommand = commands->commands[index];
181 if (moveCommand->Execute != NULL)
182 {
183 printf("<");
184 moveCommand->Execute();
185 printf("> ");
186 }
187 }
188 printf("\n");
189 }
190}
191
192
199{
200 if (commands != NULL)
201 {
202 for (size_t index = 0; index < commands->commands_count; index++)
203 {
204 MoveCommand* moveCommand = commands->commands[index];
205 MoveCommand_Show(moveCommand->commandToken, moveCommand->commandName);
206 }
207 }
208}
209
218static void MoveProcessor_ExecuteMoveList(const char *moveList)
219{
220 MoveCommandList commandList;
221
222 MoveCommandList_Initialize(&commandList);
223
224 if (_MoveProcessor_ParseMoves(moveList, &commandList))
225 {
226 _MoveProcessor_ExecuteMoves(&commandList);
227 }
228 MoveCommandList_Clear(&commandList);
229}
230
231
240static void MoveProcessor_ShowMoveList(const char *moveList)
241{
242 MoveCommandList commandList;
243 MoveCommandList_Initialize(&commandList);
244 if (_MoveProcessor_ParseMoves(moveList, &commandList))
245 {
246 _MoveProcessor_ShowMoves(&commandList);
247 }
248 MoveCommandList_Clear(&commandList);
249}
250
251
252//=============================================================================
253//=============================================================================
254
274// ! [Using NullObject in C]
276{
277 printf("\nNullObject Exercise\n");
278
279 // A stream of recognized and unrecognized move commands. The
280 // unrecognized commands do nothing.
281 const char* moveString = "ur#ld!lr";
282 printf(" Showing the move commands:\n");
283 MoveProcessor_ShowMoveList(moveString);
284
285 printf(" Executing the move commands:\n");
286 printf(" %s -> ", moveString);
288
289 printf(" Done.\n");
290}
291// ! [Using NullObject in C]
void NullObject_Exercise(void)
Example of using the Null Object Pattern.
static void MoveCommandRight_Execute(void)
Represents the Move Right command.
static void MoveProcessor_ExecuteMoveList(const char *moveList)
Parse and execute the given list of move commands, where each command is represents by a single chara...
static void _MoveProcessor_ExecuteMoves(MoveCommandList *commands)
Helper method to execute all the given commands.
static void MoveCommandUp_Execute(void)
Represents the Move Up command.
static void MoveCommandDown_Execute(void)
Represents the Move Down command.
static void _MoveProcessor_ShowMoves(MoveCommandList *commands)
Show the command character and name of the command for all commands in the given list of commands.
static void MoveCommand_Show(char commandToken, const char *commandName)
Show the move command and its name followed by a newline.
static bool _MoveProcessor_ParseMoves(const char *moveList, MoveCommandList *commandList)
Represents the processor that translates the move list into a list of MoveCommand objects then either...
static void MoveProcessor_ShowMoveList(const char *moveList)
Parse and display the given list of move commands, where each command is represents by a single chara...
static void MoveCommandNone_Execute(void)
Represents the Do Nothing command. This is the Null "Object" for this exercise.
static void MoveCommandLeft_Execute(void)
Represents the Move Left command.
MoveCommand * MoveCommand_Create(char commandToken, const char *commandName, ExecuteFunction executeFunction)
Create a MoveCommand object and initialize it with the given arguments.
void MoveCommandList_Clear(MoveCommandList *commandList)
Clear the given MoveCommandList, freeing up any allocated resources, so the list can be reused.
void MoveCommandList_Initialize(MoveCommandList *commandList)
Initialize the given MoveCommandList object. This should be the first function called for an uninitia...
bool MoveCommandList_Add(MoveCommandList *commandList, MoveCommand *moveCommand)
Add a given MoveCommand object to the given MoveCommandList object. The MoveCommandList takes ownersh...
Declaration of the MoveCommandList structure along with the support functions, MoveCommandList_Initia...
Declaration of the NullObject_Exercise() function as used in the Null Object Pattern.
Represents a move command. A move command has a name and the command character that represents the co...
char commandToken
The character that represents this move command in a string.
const char * commandName
The name of this move command.
ExecuteFunction Execute
The function to call to execute the move command (this varies for each command)
Represents a list of MoveCommand objects.
MoveCommand ** commands
Array of pointers to MoveCommand objects.
size_t commands_count
Number of commands in the commands array.