Description: Avoids coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain.
Why used: Logging requests often need to pass through multiple handlers (Console, File, API) based on severity. The chain allows a log message to optionally be processed by multiple handlers or filtered out at any stage.
2. Singleton Pattern
Description: Ensures a class has only one instance and provides a global point of access to it.
Why used: A Logger typically needs to be globally accessible to avoid passing it around every method. It also aggregates configuration (log levels, sinks) in a central place.
Phase 5: Code Key Methods
Java Implementation
Phase 6: Discussion
Async Logging
Q: "How to handle High Throughput logging?"
A: "Use a BlockingQueue. The log() method puts the message into the queue (Producer). A separate background thread (Consumer) polls the queue and calls chain.logMessage(). This decouples the Main Thread from I/O operations."
Extensibility
Q: "How to add new sinks (e.g. Splunk)?"
A: "Open/Closed Principle. Just extend LogHandler to create SplunkHandler and add it to the chain setup code. No existing handler code needs to change."
Factory Pattern
Q: "How to manage creating loggers?"
A: "A LoggerFactory.getLogger(Class) is common. It might return the same Singleton or different named loggers with specific configs."
SOLID Principles Checklist
S (Single Responsibility): LogHandler does only handling. Logger manages the instance.
O (Open/Closed): Add new Handlers without modifying existing ones.
L (Liskov Substitution): All Handlers are interchangeable in the chain.
I (Interface Segregation): N/A.
D (Dependency Inversion): Logger depends on LogHandler abstraction.