Intro to Design Patterns

📢 This article was translated by gemini-3-flash-preview

“Each design pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” The core of design patterns is providing solutions to recurring problems, allowing developers to easily reuse successful designs and architectures.

A design pattern generally consists of 4 basic elements:

  1. Pattern Name: A handle used to describe the design problem, its solutions, and consequences in a word or two.
  2. Problem: Describes when to apply the pattern.
  3. Solution: Describes the elements that make up the design, their relationships, responsibilities, and collaborations.
  4. Consequences: The results and trade-offs of applying the pattern.

Design patterns identify the classes and instances involved, their roles, collaborations, and responsibility distribution. Each pattern focuses on a specific object-oriented design problem or point, describing when to use it, whether it works under specific constraints, and the trade-offs involved. Based on their purpose, design patterns are divided into three main categories:

Creational patterns deal with object creation; Structural patterns handle the composition of classes or objects; Behavioral patterns describe how classes or objects distribute responsibilities.

Design Patterns - English

CreationalStructuralBehavioral
ClassFactory MethodAdapter (Class)Interpreter
Template Method
ObjectAbstract Factory
Builder
Prototype
Singleton
Adapter (Object)
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Chain of Responsibility
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor

Creational Design Patterns

Creational patterns abstract the instantiation process. They help make a system independent of how its objects are created, composed, and represented. A class-creational pattern uses inheritance to vary the class being instantiated, while an object-creational pattern delegates instantiation to another object.

As systems evolve to depend more on object composition rather than class inheritance, creational patterns become more important. In these cases, the focus shifts from hard-coding a fixed set of behaviors to defining a small set of basic behaviors that can be composed into any number of complex ones. Creating an object with specific behavior then requires more than just instantiating a class.

There are two recurring themes in these patterns:

  1. They encapsulate knowledge about which concrete classes the system uses.
  2. They hide how instances of these classes are created and put together. The system only knows about the objects through the interfaces defined by abstract classes.

This provides significant flexibility in what is created, who creates it, how it’s created, and when. They allow a system to be configured with “product” objects that vary widely in structure and functionality. This configuration can be static (at compile-time) or dynamic (at runtime).

Structural Design Patterns

Structural patterns are concerned with how classes and objects are composed to form larger structures. Structural class patterns use inheritance to compose interfaces or implementations. A simple example is using multiple inheritance to combine two or more classes into one, resulting in a class that possesses the properties of all its parents. This is particularly useful for making independently developed libraries work together (e.g., the class-based Adapter pattern). Generally, an adapter makes one interface compatible with others, providing a unified abstraction. To do this, a class adapter privately inherits from an adaptee class and expresses its interface using the adaptee’s interface.

Structural object patterns don’t compose interfaces or implementations; instead, they describe ways to assemble objects to realize new functionality. Since object composition can be changed at runtime, it offers greater flexibility that is impossible with static class composition.

Behavioral Design Patterns

Behavioral patterns focus on algorithms and the assignment of responsibilities between objects. They describe not just patterns of objects or classes but also the communication patterns between them. These patterns characterize complex control flows that are difficult to track at runtime, shifting the developer’s attention away from control flow to focus on how objects are interconnected.

Behavioral class patterns use inheritance to distribute behavior between classes. The Template Method is a common and simple example. It provides an abstract definition of an algorithm, defining it step-by-step. Each step calls either an abstract operation or a primitive operation, with subclasses implementing the abstract operations. Another example is the Interpreter, which represents a grammar as a class hierarchy and implements an interpreter as an operation on instances of those classes.

Behavioral object patterns use object composition rather than inheritance. Some describe how a group of peer objects cooperate to perform a task that no single object can carry out alone. A key issue here is how peer objects stay aware of each other. Peer objects could maintain explicit references to each other, but that increases coupling. In the extreme case, every object would need to know about every other object. The Mediator pattern avoids this by introducing a mediator object between peers, providing the indirection required for loose coupling.

https://refactoringguru.cn/design-patterns