Design Patterns Brief

Strategy Pattern

“Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. This pattern lets the algorithm vary independently of the clients that use it”
You design a common Strategy interface (for example, CompressionStrategy) and implement multiple concrete strategies (e.g. ZipCompression, RarCompression). A context class holds a reference to a strategy and delegates to it. At runtime the client picks and switches strategies as needed, without changing the context’s code.

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”
One object (Subject) maintains a list of observers and sends updates to them when its state changes. Observers implement a common interface and register with the subject. When the subject’s state updates (e.g. data model change), it calls notifyObservers(), causing each observer’s update method to run. This decouples subjects and observers.

Decorator Pattern

“Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality” You have a base interface or class (e.g. Beverage) and concrete implementations (Espresso, Tea). Instead of subclassing every possible combination (e.g. EspressoWithMilk), you create Decorator classes that wrap a Beverage and add behavior (e.g. MilkDecorator). Multiple decorators can wrap an object at runtime to accumulate behaviors. Each decorator has the same interface, so it’s transparent to clients.

Factory Method Pattern

“Factory Method pattern defines an interface/method (a.k.a. factory method) for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses” You declare a factory method in a base creator class (or interface) (e.g., createDocument() in Application). Concrete subclasses override it to return specific products (e.g., SpreadsheetDocument, TextDocument). Clients call the factory method on the base class interface, but the actual subclass controls the product’s type. This decouples product creation from client code.

Abstract Factory Pattern

“Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes” You define an abstract factory interface (e.g., GUIFactory) with methods to create various related products (e.g. createButton(), createCheckbox()). Concrete factories (WindowsFactory, MacFactory) implement these methods to produce OS-specific components. Client code uses the abstract factory interface to create components, so it stays agnostic of concrete classes. This ensures products from the same family are used together.

Singleton Pattern

“Singleton pattern ensures a class has only one instance, and provides a global point of access to it” You make a class constructor private and provide a static method (e.g. getInstance()) that returns the sole instance. On the first call it creates the instance; subsequent calls return the existing one. Often also make the instance variable static so it’s shared. This guarantees only one object exists.

Command Pattern

“Command pattern encapsulates a request as an object (Command), thereby letting you parameterize other objects (Receiver) with different requests, queue or log requests, and support undoable operations” You create a Command interface with an execute() method. Concrete command classes wrap a receiver and the action to perform (e.g., LightOnCommand holds a Light and its on() action). An invoker (e.g. a button or menu item) holds a command reference and calls execute() on it. Clients can pass commands to invokers at runtime. Because commands are objects, you can store, queue or undo them.

Adapter Pattern

“Adapter pattern converts the interface of a class into another that the clients expect, making classes with incompatible interfaces able to work together” You have an existing class (Adaptee) with one interface, but the client expects a different interface (Target). The Adapter class implements the Target interface and holds an instance of Adaptee. Its methods translate calls from the Target interface to calls on the Adaptee. This way, the client can use the adaptee through the adapter as if it were a different type.

Facade Pattern

“Facade pattern provides a unified interface to a set of interfaces in a subsystem. It makes the subsystem easier to use by providing a higher-level interface” You create a single Facade class that wraps a complex subsystem of many classes and offers simplified methods. The client calls the facade’s easy methods, which internally call the appropriate subsystem classes. This hides subsystem complexity and reduces coupling. Subsystem classes can still be used directly if needed, but clients can rely on the facade for common tasks.

Template Method Pattern

“Template Method is a behavioral design pattern that allows you to define a skeleton of an algorithm in a base class and let subclasses override steps without changing the overall algorithm’s structure” In a base class (abstract), you define a final templateMethod() that calls several primitive operations (some abstract, some with default implementation). Subclasses override these primitive methods to provide behavior for specific steps. The template method enforces the algorithm’s order. The client calls templateMethod(), and the subclass-specific details execute within.

Iterator Pattern

“Iterator design pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation” You define an Iterator interface (hasNext(), next()) and an Aggregate interface (createIterator()). The concrete aggregate (e.g. a collection or composite) returns an iterator. The client then loops using the iterator to traverse elements. This allows traversing different collections uniformly, hiding details of how elements are stored.

Composite Pattern

“Composite design pattern composes objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions uniformly” You define a Component interface with operations (e.g. render()). Leaf classes implement the interface for indivisible objects (e.g. Circle). The composite class implements the interface and contains a list of Components (both leaves and composites). Methods (e.g. render()) on the composite iterate over children and call their methods. The client interacts with components through the common interface and doesn’t need to know if it’s a leaf or composite.

State Pattern

“State pattern allows an object (Context) to alter its behavior when its internal state changes. The object will appear to change its class” You define a State interface with methods for actions. Concrete state classes implement the behavior for each state (e.g. OnState, OffState). The context class holds a reference to a state object and delegates state-specific behavior to it. When events occur, the state object may change the context’s current state to another. Thus the context’s behavior changes without a complex conditional.

Proxy Pattern

“Provide a surrogate or placeholder for another object to control access to it” The proxy object implements the same interface as the real subject. Clients hold a reference to the proxy. When a client calls a method, the proxy can perform actions before/after forwarding the call to the real object. Types of proxies: Virtual Proxy (lazy-load a heavy object), Remote Proxy (represent an object in a different address space), Protection Proxy (check access permissions), Caching Proxy.

Bridge Pattern

Bridge pattern decouples an abstraction from its implementation so that the two can vary independently You separate a class into two hierarchies: the Abstraction (defines high-level control) and the Implementor (defines low-level operations). The abstraction holds a reference to an implementor interface. Concrete abstractions delegate calls to the implementor. This allows you to change or extend abstractions and implementations independently.

Builder Pattern

Builder Pattern constructs a complex object step by step, and the final step will return the object. The process of constructing an object should be generic so that it can be used to create different representations of the same object You create a Builder interface with methods for each part of the product, and a Director that uses a builder to construct the final object. Concrete builders implement the steps to build different representations. Clients use the director and builder to assemble the product incrementally. This separates object construction from representation.

Chain of Responsibility Pattern

“Chain of Responsibility is a behavioral design pattern that lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain” You have a series of handler objects linked together. Each handler has a method like handle(request). A handler either processes the request or forwards it to its successor in the chain. The client sends the request to the first handler in the chain. This allows multiple potential handlers to attempt to process the request, without the sender knowing which handler (if any) will handle it.

Flyweight Pattern

“The Flyweight pattern reduces the number of objects created, decreasing the memory footprint and increasing performance. Flyweight shares similar kinds of objects that are used repeatedly, instead of creating new ones” When many objects share the same data, you factor out that intrinsic state into shared flyweight objects, and store the unique extrinsic state externally. Clients request flyweights from a factory by specifying intrinsic data. The factory returns existing flyweight if present or creates a new one. This way, many contexts can share a small set of flyweight instances.

Interpreter Pattern

“Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language” ou design a class structure (often a tree) that represents grammar rules of a language. Each grammar rule is a class implementing an interpret() method. Client builds (or is given) an abstract syntax tree of expression objects and then calls interpret(context) on the root. The interpreter walks the tree to evaluate or process the expression.

Mediator Pattern

“Mediator is a behavioral design pattern that lets you reduce chaotic dependencies between objects. The pattern restricts direct communications between the objects and forces them to collaborate only via a mediator object” You define a Mediator interface with a method like notify(sender, event). Concrete mediator classes implement it and hold references to component objects. Components have a reference to the mediator and, instead of communicating directly with each other, they call the mediator. The mediator then routes or coordinates interactions among components. This centralizes complex communication logic.

Memento Pattern

“The Memento pattern lets you make full copies of an object’s state, including private fields, and store them separately from the object. […] Mementos are linked to the originator and can restore its state” The Originator class can produce a Memento (snapshot) of its current state and restore state from a memento. The Memento is a separate object (often immutable) that holds the internal state. A Caretaker class keeps track of mementos (e.g. a stack for undo). The originator exposes methods like save() and restore(m). External objects cannot modify the memento’s state.

Prototype Pattern

“Prototype pattern lets you produce a copy of an object without knowing anything about its type” You define a clone() method in a class (or an interface) which returns a copy of the object. The client, which may not know the concrete class, just calls clone() on an existing instance (the prototype) to get a new object. This is useful when creating a new instance is expensive or when dynamic cloning is needed.

Visitor Pattern

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates” You define a Visitor interface with visit methods for each concrete element type (e.g. visitA(ConcreteA a), visitB(ConcreteB b)). Each element class implements an accept(Visitor v) method that calls v.visitX(this). This decouples operations from object structure. New visitors (operations) can be added without modifying the element classes.

Commonly Tested OOP Design Patterns in LLD Interviews

  1. Strategy Pattern
  2. Observer Pattern
  3. Factory Method / Abstract Factory
  4. Singleton Pattern
  5. Decorator Pattern
  6. Adapter Pattern
  7. Command Pattern
  8. Composite Pattern
  9. Chain of Responsibility
  10. State Pattern
  11. Flyweight Pattern