Recap: Logger Factory
Part of the Object Oriented Programming section of Coddy's C journey — lesson 57 of 61.
Challenge
EasyLet's build a Logger Factory — a system that demonstrates the power of combining the Factory pattern with polymorphism. Your factory will create different logger implementations based on a configuration flag, allowing code to switch between verbose console output and silent "dummy" logging without changing how loggers are used.
You'll organize your code across three files:
logger.h: Define aLoggerstruct that acts as an interface — it should contain a function pointer forlogthat takes aLogger*and aconst char*message. Declare your factory functioncreate_loggerthat takes an integer flag (1 for console, 0 for dummy) and returns aLogger*. Also declare afree_loggerfunction for cleanup.logger.c: Implement two concrete logger types. TheConsoleLoggerembedsLoggeras its first member and has a log function that prints messages in the format[LOG] message. TheDummyLoggeralso embedsLoggerbut its log function does nothing — it simply returns without printing. Create constructor functions for each type that allocate memory and wire up the appropriate log function. Then implementcreate_loggeras a factory that checks the flag and returns the appropriate logger type as aLogger*. Implementfree_loggerto release memory.main.c: Read an integer (1 or 0) to determine which logger to create. Use your factory to create the appropriate logger, then call itslogfunction with two messages:"Starting application"and"Shutting down". Finally, free the logger.
Your program will receive one input: an integer indicating the logger type (1 for console, 0 for dummy).
Example output when the input is 1:
[LOG] Starting application
[LOG] Shutting downExample output when the input is 0:
(No output — the dummy logger silently ignores all messages)
The elegance here is that main.c uses the logger identically regardless of which type it receives. The factory decides what to create, and polymorphism ensures the correct behavior executes. This pattern is invaluable in real applications where you might want verbose logging during development but silent operation in production.
Try it yourself
#include <stdio.h>
#include "logger.h"
int main() {
// Read the logger type flag (1 for console, 0 for dummy)
int flag;
scanf("%d", &flag);
// TODO: Use the factory to create the appropriate logger
// TODO: Call the logger's log function with "Starting application"
// TODO: Call the logger's log function with "Shutting down"
// TODO: Free the logger
return 0;
}
All lessons in Object Oriented Programming
1Modular Programming Basics
Header FilesInclude GuardsSource FilesStatic FunctionsRecap: Modular Calculator4Encapsulation
Opaque Pointers ConceptDefining Opaque StructsGetters and SettersValidation in SettersRecap: Secret Box2Objects and Methods
Structs as ObjectsThe 'Self' PointerConst CorrectnessPointer vs ValueHelper MethodsRecap: Point Manager5Project: Simple Bank Account
Project SetupImplementation of Account3Object Lifecycle
Constructor PatternDestructor PatternStack InitializationDeep CopyRecap: String Wrapper6Inheritance via Composition
Struct EmbeddingThe First Member RuleAccessing Parent MembersUpcastingRecap: Shape Hierarchy