Repo Link: https://codeberg.org/amadeus404/lld-patterns
Basics
- Abstraction
- Encapsulation
- Polymorphism
- Inheritance
Composition
In object-oriented programming, composition is a design principle where a larger, more complex object is built by combining smaller, simpler objects.
Instead of a class inheriting behavior from a parent class (the “is-a” relationship), an object takes ownership of other objects to get its behavior (the “has-a” relationship).
Strategy Pattern
Identify the aspects of your application that vary and separate them from what stays the same
- Take the parts that vary and encapsulate them so that later I can extend the parts that vary without affecting those that don’t. Program to an interface, not an implementation
- Create an interface for the behavior that keeps changing → implement the various behaviors using that interface.
- The actual class that needs those things is just using that interface and is not worried about the actual implementation, it will pull whatever is necessary.
- Programming to an interface just means programming to a supertype → I don’t actually have to use the interface Favor composition over inheritance
- Instead of inheriting their behavior, the classes get their behavior by being composed with the right behavior object
Strategy Pattern - Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it
Observer Pattern
Observer Pattern - Defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically
TODO - Read about Publish-Subscribe Pattern and how it is different from observer pattern
Strive for loosely coupled designs between objects that interact
TODO - Implement something using the Observer pattern in the Java Swing Library TODO - What is Java Beans? What is it used for?
Push vs Pull Model
Push Model
Subject sends data to observers via update(data). Benefits:
- Observers don’t need a reference to the subject
- Decoupled — observer only depends on the data object/type
- Simpler observer interface
Downsides:
- Subject decides what data is important (might send too much or too little)
- All observers get everything, even if they only need a subset
- If data changes shape, every observer’s update() signature breaks
Pull Model
Subject just says “I changed!” and observers call getters to fetch what they need. Benefits:
- Each observer pulls only what it needs — efficient for selective consumers
- Subject doesn’t need to anticipate what observers want
- Adding new fields to subject doesn’t break observers
Downsides:
- Observer needs a reference to the concrete subject (coupling)
- More complex observer interface (or stored subject reference)
- Observer needs to know what to ask for and when
Which one to use?
- Push when all observers need essentially the same data and data shape is stable
- Pull when observers need different slices of data, or the subject’s state is complex and evolving
Decorator Pattern
Open Close Principle: Classes should be open for extension, but closed for modification
The decorator adds its own behavior before and/or after delegating to the object it decorates to do the rest of the job.
*Decorator Pattern - Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
TODO - Do something with the Java IO Library