Skip to content

Design Patterns (GoF)

Design Patterns (GoF)

Gang of Four Software Design Patterns

1. Overview of GoF Design Patterns: A System of Proven, Reusable Solutions to Recurring Design Problems

    flowchart LR
    A["Recurring design problems<br/>(duplication, coupling, maintainability)"] --"Apply 23<br/>proven patterns"--> B["Creational, structural,<br/>and behavioral pattern families"] --"Flexible,<br/>reusable design"--> C["Software architecture<br/>resilient to change"]

    style A fill:#FFEBEE,stroke:#D32F2F,color:#000
    style B fill:#E3F2FD,stroke:#1976D2,color:#000
    style C fill:#E8F5E9,stroke:#388E3C,color:#000
  

Definition: A body of design knowledge consisting of 23 software design patterns cataloged by Erich Gamma and three co-authors (the “Gang of Four”), classifying proven solutions to recurring object-oriented design problems into Creational, Structural, and Behavioral patterns.

Characteristics: (Design reusability) A reusable solution at the design level, independent of any specific language or technology. (A shared design language) Improves communication efficiency among developers through a common design vocabulary (pattern names). (Complementary use) Used complementarily with SOLID principles and Clean Architecture.


2. Core Structure of GoF Design Patterns

a. Creational, Structural, and Behavioral Patterns

    flowchart TD
    subgraph R1["​"]
        direction LR
        CR["Creational Patterns<br/>encapsulate object creation<br/>flexible instance creation"]
        ST["Structural Patterns<br/>compose classes/objects<br/>into larger structures"]
        BE["Behavioral Patterns<br/>distribute responsibility/algorithms<br/>and collaboration between objects"]
    end

    style CR fill:#E3F2FD,stroke:#1976D2,color:#000
    style ST fill:#F3E5F5,stroke:#7B1FA2,color:#000
    style BE fill:#FFF3E0,stroke:#F57C00,color:#000
    style R1 fill:none,stroke:none
  

Creational Patterns (5)

PatternPurposeKey Characteristics
SingletonGuarantee only one instance of a classProvides a global access point, shares a resource
Factory MethodDelegate object creation to a subclassSeparates creation code from usage code
Abstract FactoryConsistently create a family of related objectsCreates platform-independent UI components
BuilderConstruct a complex object step by stepProduces varied results via the same process
PrototypeCreate a new object by cloning an existing oneCopying objects that are expensive to initialize

Structural Patterns (7)

PatternPurposeKey Characteristics
AdapterConnect incompatible interfacesLegacy system integration, acts as a wrapper
DecoratorDynamically add functionality to an objectExtends responsibility without inheritance, stackable
FacadeProvide a simple interface to a complex subsystemAPI Gateway, library wrapping
ProxyAct as a surrogate/controlled access to another objectLazy loading, access control, caching
CompositeRepresent part-whole hierarchies as a treeFile systems, UI component trees
BridgeVary abstraction and implementation independentlySeparates different implementations per platform
FlyweightEfficiently share large numbers of similar objectsGame particles, character font caching

Behavioral Patterns (11)

PatternPurposeKey Characteristics
ObserverAutomatically notify many objects of a state changeEvent-driven, Pub/Sub-based
StrategyEncapsulate an algorithm to make it swappableRemoves if-else chains, swaps algorithms at runtime
CommandEncapsulate a request as an objectUndo support, queuing/logging
Template MethodDefine an algorithm’s skeleton, delegate detailsPreserves the common flow, isolates variation points
IteratorStandardize traversal of a collectionSequential access without exposing internal structure
Chain of ResponsibilityPass a request along a chain of handlersMiddleware, filter pipelines
StateChange behavior based on an object’s stateImplements a finite state machine (FSM)

b. Key Pattern Examples — Singleton, Observer

Singleton — Guaranteeing a Single Instance

    flowchart LR
    C1["Client A"] --> S["Singleton Instance<br/>(only one exists)<br/>config manager, DB connection,<br/>log manager"]
    C2["Client B"] --> S
    C3["Client C"] --> S

    style S fill:#1E3A5F,stroke:#1E3A5F,color:#fff
  
CategoryDescription
When to applyWhen global state management is needed and a single instance must be guaranteed
AdvantagesResource sharing, memory savings, consistent state access
CaveatsRequires double-checked locking in multithreaded environments, harder to test
Common examplesConfig, DB connection pool, Logger, thread pool

Observer — Automatic Notification of State Change

    flowchart LR
    PUB["Subject (Publisher)<br/>a state change occurs<br/>manages the subscriber list"]

    subgraph OBS["Observer (Subscriber)"]
        direction TB
        O1["Observer A<br/>(email notification)"]
        O2["Observer B<br/>(SMS notification)"]
        O3["Observer C<br/>(push notification)"]
    end

    PUB --"notify()"--> O1
    PUB --"notify()"--> O2
    PUB --"notify()"--> O3

    style PUB fill:#1E3A5F,stroke:#1E3A5F,color:#fff
    style O1  fill:#E3F2FD,stroke:#1976D2,color:#000
    style O2  fill:#F3E5F5,stroke:#7B1FA2,color:#000
    style O3  fill:#FFF3E0,stroke:#F57C00,color:#000
  
CategoryDescription
When to applyWhen a change in one object’s state must propagate to several other objects
AdvantagesLoose coupling, dynamic add/remove of subscribers, enables event-driven architecture
Common examplesGUI event handling, Kafka Pub/Sub, state management (Redux), Spring ApplicationEvent

3. Expected Benefits and Application of GoF Design Patterns

CategoryExpected BenefitsApplication and Practical Use
Code qualityApplying proven patterns reduces coupling and increases cohesionRemove conditionals with Strategy, separate responsibilities with Decorator
MaintainabilityFlexible design minimizes the blast radius of changeImplement event-driven extensibility with Observer/Command patterns
Communication efficiencyPattern names concisely convey design intentReduce communication cost in code reviews and design docs by using pattern names
Architecture integrationCombines with MSA/Clean Architecture to strengthen extensibilityInject dependencies with Factory, simplify microservice APIs with Facade