Fact-checked by Grok 2 weeks ago

Delegation pattern

The delegation pattern is a fundamental technique in where an object forwards or delegates specific responsibilities, method calls, or tasks to another collaborating object, known as the delegate, rather than handling them internally. This approach relies on to achieve behavioral and polymorphism, allowing the delegator to dynamically assign and change the delegate at without altering its own structure. Unlike , which establishes a fixed "is-a" relationship, delegation uses a flexible "has-a" or "uses-a" association, promoting and adaptability in . In practice, the pattern involves a delegator that maintains a to the delegate object—which in reference-counted languages like is often weak to avoid retain cycles—invoking its methods in response to events or requests. The delegate typically conforms to a defined or specifying the expected behaviors, ensuring and clear contracts between objects. This structure is evident in frameworks like iOS's UIKit, where components such as UITableView delegate data sourcing and user interactions to conforming objects, enabling modular and reusable code. Delegation also underpins more complex patterns, including for interface translation and Decorator for extending functionality without subclass proliferation. The delegation pattern offers significant advantages in and extensibility, as it isolates details and shields the delegator from changes in the delegate's internals, reducing ripple effects across the codebase. By favoring over deep hierarchies, developers can mitigate issues like base class problem and support single- languages more effectively, as seen in proposals for automated tools that generate forwarding code to simplify . However, it may introduce slight overhead from method indirection and requires careful of delegate lifecycles to prevent memory leaks. Overall, embodies the principle of "favor ," a cornerstone of effective object-oriented recommended by experts like .

Fundamentals

Definition

The delegation pattern is a behavioral design mechanism in object-oriented programming wherein an object, referred to as the delegator, forwards or delegates a invocation or responsibility to another object, known as the delegate, rather than handling it internally. This approach allows the delegator to leverage the delegate's specialized behavior while maintaining a clear , enabling the delegator to focus on its primary role without embedding the delegated functionality. Key characteristics of the delegation pattern include its promotion of between objects, adherence to the by distributing tasks, and provision of runtime flexibility through dynamic method forwarding, which contrasts with static hierarchies. Unlike , which establishes a fixed IS-A , delegation relies on a HAS-A , where the delegator holds a to the delegate and explicitly or implicitly routes requests to it. This pattern supports polymorphism by allowing interchangeable delegates at runtime and enhances encapsulation by hiding the delegate's implementation details from external clients. In , the delegator is the client object that receives an initial request and chooses to forward it, while the delegate is the object that performs the actual computation or ; explicit delegation involves direct calls to the delegate, whereas implicit delegation may use mechanisms like in languages supporting it. The pattern presupposes foundational object-oriented principles such as polymorphism, which enables uniform interfaces across objects, and encapsulation, which protects internal state through controlled access, ensuring that delegation operates within a modular, reusable structure.

Motivation

The delegation pattern addresses key challenges in object-oriented software design, particularly those arising from inheritance hierarchies. Inheritance often results in tight coupling between base and derived classes, where modifications to a parent class can inadvertently affect numerous subclasses, leading to fragility and maintenance difficulties. This tight coupling violates the open-closed principle (OCP), as extending behavior typically requires altering existing code or creating extensive subclass proliferations, rather than simply adding new components. Additionally, inheritance struggles with modeling dynamic roles or contexts that evolve over an object's lifetime, often necessitating redundant implementations or multiple class instances to represent the same entity. By favoring , the delegation pattern mitigates these issues through a delegator-delegate , where one object forwards responsibilities to another, enabling modular and flexible designs. This approach reduces code duplication by reusing behavior via rather than replication, while supporting changes to delegated components without recompiling or modifying the delegator's . It promotes the by allowing extensions through new delegate implementations, keeping the core class closed to modification, and enhances overall system modularity by decoupling the delegator from specific implementations. The pattern emerged in the late 1970s within artificial intelligence and early programming languages, gaining prominence in the 1980s with languages like Smalltalk and further in the 1990s alongside the rise of object-oriented design patterns. The term "delegation" was coined by Henry Lieberman in his 1986 paper "Using Prototypical Objects to Implement Shared Behavior in Object Oriented Systems". It is discussed in the seminal work Design Patterns: Elements of Reusable Object-Oriented Software (1994) by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (the "Gang of Four"), where it is positioned as a behavioral technique to make composition as reusable as inheritance, influencing patterns like Strategy and State. Delegation proves particularly valuable in scenarios where a class must vary its algorithms or offload tasks—such as event handling or data processing—while preserving a stable public interface, thereby avoiding the rigidity of subclassing.

Design and Implementation

UML Representation

The delegation pattern is typically represented in UML class diagrams through a structural blueprint that highlights the composition-based relationship between the delegator and the delegate. The central elements include a Delegator class, which holds a reference (often as an attribute) to a Delegate interface or class, and methods within the Delegator that forward invocations to corresponding methods in the Delegate. This is depicted using a solid line association arrow from the Delegator to the Delegate, indicating the compositional link, with the arrowhead pointing to the Delegate to show directionality of delegation. For explicit notation of the forwarding behavior, UML employs a dependency relationship stereotyped as <<delegate>>, shown as a dashed from the Delegator's to the Delegate's corresponding or , emphasizing the or compile-time forwarding of requests. Multiplicity may be included on the association, such as 1 (Delegator) to 0..* (Delegates), to indicate support for multiple delegate instances if applicable, though single-delegate scenarios often use 1:1. In UML sequence diagrams, the delegation pattern illustrates the dynamic interaction flow, with lifelines representing the Client, Delegator, and Delegate objects. The sequence begins with a synchronous from the Client to the Delegator (e.g., invoking a like performTask()), followed by the Delegator sending a matching to the Delegate (e.g., delegate.performTask()), and return messages flowing back along the same paths to complete the response. This notation uses arrows for messages and dashed lines with arrowheads for returns, capturing the temporal order of delegation without implying hierarchies. Variations in UML representations distinguish static from dynamic delegation: static delegation, where the delegate is fixed at compile-time, is shown with a direct, non-parameterized in class diagrams; dynamic delegation, allowing selection of delegates, may incorporate notes or parameterized dependencies to denote variability in the association.

Code Examples

The delegation pattern can be illustrated through simple, executable code snippets in various languages, highlighting how a delegator object forwards responsibilities to a delegate. These examples focus on method delegation, demonstrating for flexible behavior.

Pseudocode Example

A generic representation shows the core forwarding mechanism, where a delegator object holds a to a delegate and invokes its methods directly. This approach encapsulates the delegation logic without assuming specific language syntax.
class Delegator {
    Delegate delegate;

    Delegator(Delegate d) {
        delegate = d;
    }

    void processRequest(Request r) {
        if (delegate != null) {
            delegate.processRequest(r);
        } else {
            // Fallback: handle request locally or throw error
            handleFallback(r);
        }
    }

    void handleFallback(Request r) {
        // Default implementation, e.g., log or basic processing
        print("Request processed locally: " + r.getData());
    }
}

class Delegate {
    void processRequest(Request r) {
        // Specialized processing
        print("Delegate handling: " + r.getData());
    }
}
This pseudocode demonstrates forwarding the processRequest method from the delegator to the delegate, including a null check for basic error handling to prevent runtime exceptions.

Java Example

In Java, delegation is often implemented using interfaces to define the contract for the delegate, allowing the delegator to swap implementations at runtime. Consider a Printer class that delegates formatting and output to a Formatter delegate.
java
// Delegate interface
interface Formatter {
    String format(String message);
}

// Concrete delegate implementation
class UpperCaseFormatter implements Formatter {
    @Override
    public String format(String message) {
        return message.toUpperCase();
    }
}

// Delegator class
class Printer {
    private Formatter formatter;

    public Printer(Formatter formatter) {
        this.formatter = formatter;
    }

    public void print(String message) {
        if (formatter != null) {
            String formatted = formatter.format(message);
            System.out.println(formatted);
        } else {
            // Fallback: print without formatting
            System.out.println("Fallback: " + message);
        }
    }

    public void setFormatter(Formatter formatter) {
        this.formatter = formatter;
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        Formatter upperFormatter = new UpperCaseFormatter();
        Printer printer = new Printer(upperFormatter);
        printer.print("Hello, Delegation!");  // Outputs: HELLO, DELEGATION!
        
        printer.setFormatter(null);
        printer.print("No formatter");  // Outputs: Fallback: No formatter
    }
}
This example shows how the Printer delegates the format responsibility to the Formatter via interface composition, with error handling via a null check that falls back to unformatted output. The design promotes loose coupling and extensibility.

Python Example

Python supports dynamic delegation through duck typing and the __getattr__ special method, which intercepts attribute or method access and forwards it to a composed object. This enables transparent method forwarding without explicit interface definitions.
python
import json

class Serializer:
    def __init__(self, instance):
        self.instance = instance
    
    def to_json(self):
        return json.dumps(self.instance.__dict__)

class Employee:
    def __init__(self, name, age, salary, use_delegation=True):
        self.name = name
        self.age = age
        self.salary = salary
        self._use_delegation = use_delegation
    
    def __getattr__(self, name):
        if self._use_delegation and hasattr(Serializer(self), name):
            return getattr(Serializer(self), name)
        raise AttributeError(f"'Employee' object has no attribute '{name}'")
    
    # Fallback when delegation is disabled
    def to_json(self):
        return f"{{'name': '{self.name}', 'age': {self.age}, 'salary': {self.salary}}}"

# Usage
emp = Employee("Alice", 30, 50000)
print(emp.to_json())  # Outputs: {"name": "Alice", "age": 30, "salary": 50000} (via [delegation](/page/Delegation))

# Disable delegation for fallback demo
emp._use_delegation = False
print(emp.to_json())  # Outputs: {'name': 'Alice', 'age': 30, 'salary': 50000}
Here, the Employee class delegates the to_json method to an internal Serializer instance via __getattr__, leveraging Python's dynamic nature for attribute forwarding. A flag (_use_delegation) controls whether occurs, allowing demonstration of both delegated JSON output and fallback string representation for robustness.

Comparisons and Variations

With Inheritance

Inheritance in object-oriented design enables fixed, compile-time extension of functionality through "is-a" relationships, where subclasses inherit behavior and structure from superclasses, often leading to deep and potentially rigid class hierarchies. This mechanism promotes by allowing subclasses to override or extend methods, but it tightly couples the subclass to the superclass's details. Delegation provides key advantages over by mitigating the fragility problem, where modifications to a base can unexpectedly break subclasses, and by facilitating the integration of multiple behaviors without relying on , which can introduce complexity and problems in languages that support it. Instead of extending a , composes objects via "has-a" relationships, forwarding requests to delegate objects at , which enhances and allows for dynamic behavior changes without altering hierarchies. The primary trade-offs involve selecting for scenarios requiring true subtype polymorphism, such as when a fundamentally represents a specialized version of its parent (e.g., is-a ), ensuring seamless substitution and leveraging the . In contrast, delegation excels in promoting for flexibility, particularly when behaviors need to be mixed or swapped without committing to a fixed , though it requires explicit forwarding, adding a layer of . A representative example is extending a Button class in a graphical user interface framework: inheritance suits creating UI variants like a ToggleButton that is-a Button, inheriting its core rendering and interaction logic for polymorphic use in containers. Delegation, however, is preferable for event handling, as seen in Java's Swing framework, where a Button delegates action events to listener objects via methods like addActionListener, allowing flexible attachment of behaviors without subclassing the Button itself.

With Proxy Pattern

The is a structural that provides a surrogate or placeholder for another object to control access to it, enabling indirect interactions such as , caching, or without altering the original object's interface. This pattern, as described in the seminal work by the , allows the proxy to perform actions before or after forwarding a request to the real object, managing aspects like resource initialization or security checks. In contrast to , which is a behavioral technique focused on offloading specific tasks to a helper object for and flexibility, the introduces additional interception logic that goes beyond simple forwarding. emphasizes task distribution to maintain without intermediary control, whereas adds layers for optimization or protection, such as validating permissions before delegation occurs. Both patterns overlap in their use of forwarding mechanisms, where the or delegator passes calls to an underlying object, but avoids the 's extra responsibilities like caching results or handling remote invocations. This distinction ensures remains lightweight for behavioral , while serves structural needs for controlled indirection. When selecting between them, pure suits scenarios requiring simple reuse of functionality through , such as in event handling systems. The is preferable for cases demanding regulated access, like virtual proxies for on-demand object creation or protection proxies for sensitive resources in distributed environments.

Applications and Language Support

Real-World Uses

In (GUI) frameworks, the delegation pattern enables efficient event handling by allowing components to delegate user interactions to specialized listener objects. In Java's framework, components such as buttons fire that are delegated to registered ActionListener implementations, promoting and reusability across multiple components. Similarly, in JavaScript's (DOM), event delegation leverages bubbling to attach a single listener to a parent element, which handles from dynamic child elements by inspecting the event target, reducing memory overhead in large-scale web applications. Dependency injection frameworks like utilize to manage object lifecycles and resolve dependencies externally, enhancing modularity in enterprise applications. The (IoC) container delegates bean instantiation and wiring, injecting dependencies via constructors or setters based on configuration metadata, which allows developers to focus on without direct object creation. Plugin architectures in web servers exemplify delegation for extensibility, where core processes route tasks to loaded modules. In the , the core delegates request processing phases—such as authentication or content generation—to modules via predefined hooks, enabling dynamic loading of extensions like mod_rewrite without altering the server kernel. This modular delegation supports scalability in handling diverse protocols and custom functionalities. In environments, delegation chains facilitate task across distributed services, optimizing performance in high-throughput systems. API gateways act as entry points that delegate incoming requests to appropriate backend services based on rules, aggregating responses and enforcing concerns like , which reduces client complexity and improves load balancing in cloud-native architectures. Such chains minimize by avoiding direct service-to-service calls.

Support in Programming Languages

In object-oriented languages, the delegation pattern is facilitated through mechanisms that enable one object to forward method calls to another. In , interfaces provide a for delegation, allowing a to implement an and forward invocations to a delegate object, often using dynamic proxies generated at runtime to intercept and route calls dynamically. Inner classes, including anonymous ones, support concise delegation by implementing interfaces inline and encapsulating the forwarding logic within the delegating . Similarly, C# natively supports via delegates, which are type-safe function pointers that reference methods for dynamic invocation, and , which build on delegates to enable publisher-subscriber patterns where handlers are delegated without tight coupling. Scripting languages offer dynamic features that simplify delegation. employs prototypes for implicit delegation, where objects inherit properties and methods through a prototype chain; when a property is accessed on an object, the runtime delegates the lookup to the prototype if not found locally, enabling flexible behavior reuse without explicit forwarding code. In , the __getattr__ special method enables dynamic attribute delegation by intercepting missing attribute accesses and forwarding them to a wrapped object, allowing transparent proxying of an entire interface with minimal boilerplate. Functional languages integrate through features that promote . Scala's traits support delegation-like behavior via mixing, where multiple traits can be composed into a to stack implementations, forwarding or overriding specific methods while delegating others to super-trait calls, thus achieving modular reuse without deep hierarchies. Haskell's enable polymorphic by associating types with implementations of overloaded operations; instances provide the delegated behavior, allowing functions to dispatch to type-specific handlers at for . Languages lacking first-class functions, such as early versions of C++, impose limitations on , requiring manual implementation through with member objects and explicit forwarding, as function pointers alone cannot capture or member functions without additional templating or wrappers.

References

  1. [1]
    [PDF] Josh Bloch Charlie Garrod
    Delegation. • Delegation is simply when one object relies on another object for some subset of its functionality. – e.g. here, the Sorter is delegating ...
  2. [2]
    [PDF] Patterns and Delegation
    "Patterns" are about identifying common code idioms and giving them names, so they fall more easily to hand and are easier for others to read.
  3. [3]
    [PDF] Automated Delegation is a Viable Alternative to Multiple Inheritance ...
    Automated delegation could satisfy both the designers and the users of class based object oriented languages. In this paper, we discuss why automated delegation.
  4. [4]
    Design Patterns by Tutorials, Chapter 4: Delegation Pattern - Kodeco
    The delegation pattern enables an object to use another “helper” object to provide data or perform a task rather than do the task itself.Missing: software | Show results with:software
  5. [5]
    Using Prototypical Objects to Implement Shared Behavior in Object ...
    Because any object can be used as a prototype, and any messages can be forwarded at any time, delegation is the more flexible and general of the two techniques.
  6. [6]
    None
    ### Definition and Key Characteristics of the Delegation Pattern in Object-Oriented Programming
  7. [7]
    Using prototypical objects to implement shared behavior in object ...
    Because any object can be used as a prototype, and any messages can be forwarded at any time, delegation is the more flexible and general of the two techniques.
  8. [8]
    (PDF) Delegation: An important concept for the appropriate design ...
    Aug 9, 2025 · In this paper, we introduce a concept of delegation as part of an object-oriented modeling language. First, we will analyze why both inheritance ...
  9. [9]
    [PDF] Design Patterns Elements of Reusable Object-Oriented Software
    Iterator (257) Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
  10. [10]
    Specifying UML Delegation (Alternative to Inheritance) - CPlusOOP
    In summary, delegation in UML is an alternative to inheritance for sharing behavior and functionality across classes. It can be represented using different ...
  11. [11]
    Class Diagram to convey the Delegate Pattern | by David Wu - ITNEXT
    Nov 28, 2019 · The Delegate Pattern breaks up large classes into reusable components. It has three roles: Delegating Object, Protocol, and Delegate. Class ...
  12. [12]
    Delegate | Enterprise Architect User Guide - Sparx Systems
    A Delegate connector defines the internal assembly of a component's external Ports and Interfaces, on a Component diagram.
  13. [13]
    UML sequence diagrams overview of graphical notation
    UML sequence diagrams focus on message interchange between lifelines, showing the sequence of messages and their occurrence specifications.Lifeline · Occurrence · ExecutionMissing: delegation | Show results with:delegation
  14. [14]
    UML 2 Tutorial - Sequence Diagram - Sparx Systems
    A sequence diagram shows objects as lifelines with interactions as messages (arrows) over time, showing which objects communicate and what triggers those ...Sequence Diagrams · Messages · Combined FragmentsMissing: delegation | Show results with:delegation
  15. [15]
    Delegation design pattern
    ### Summary of Delegation Design Pattern
  16. [16]
    Replace Inheritance with Delegation - Refactoring.Guru
    Replacing inheritance with delegation involves creating a superclass object field, delegating methods to it, and making the superclass a helper, not a parent.
  17. [17]
    Delegation Pattern in Java: Mastering Efficient Task Assignment
    Delegation is a design pattern where an object passes on a task to a helper object. In object-oriented programming, delegation refers to evaluating a member ( ...
  18. [18]
    Python Classes: The Power of Object-Oriented Programming
    Dec 15, 2024 · This is a pretty cool Python feature. You've tried your hand at a quick example of delegation in Python to learn how a class can delegate ...
  19. [19]
    [PDF] Design Patterns: Abstraction and Reuse of Object-Oriented Design
    We discuss how design patterns impact object-oriented programming and design. We also review related work. The second part of this paper (the Appendix) ...
  20. [20]
    [PDF] Patterns and Delegation
    • The main patterns book is -- Design Patterns: Elements of Reusable Object-Oriented Software -- by. Erich Gamma et al. Known as the "gang of four, Gof" book ...
  21. [21]
    Proxy - Refactoring.Guru
    Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, ...
  22. [22]
  23. [23]
    Dependency Injection :: Spring Framework
    Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor ...Missing: delegation | Show results with:delegation
  24. [24]
    Hook Functions in the Apache HTTP Server 2.x
    A hook function is one that the Apache HTTP Server will call at some point during the processing of a request.Missing: delegation | Show results with:delegation
  25. [25]
    Pattern: API Gateway / Backends for Frontends - Microservices.io
    Implement an API gateway that is the single entry point for all clients. The API gateway handles requests in one of two ways.
  26. [26]
    Delegation Patterns for OAuth 2.0 using Token Exchange - Scott Brady
    How to handle delegation scenarios using OAuth Token Exchange, for use with microservices and API gateways.
  27. [27]
    Dynamic Proxy Classes
    A dynamic proxy class is a class that implements a list of interfaces specified at runtime such that a method invocation through one of the interfaces on an ...Missing: pattern | Show results with:pattern
  28. [28]
    Introduction to delegates and events - C# - Microsoft Learn
    Mar 31, 2022 · Delegates provide a late binding mechanism in .NET. Late Binding means that you create an algorithm where the caller also supplies at least one method.
  29. [29]
    Using Delegates (C# Programming Guide) - Microsoft Learn
    Learn how to use delegates. Delegates are an object-oriented, type safe, and secure type that safely encapsulates a method.
  30. [30]
    Programming FAQ — Python 3.14.0 documentation
    upper()) def __getattr__(self, name): return getattr(self._outfile, name) ... The delegation is accomplished via the __getattr__() method; consult the ...
  31. [31]
    Traits | Tour of Scala
    Traits are used to share interfaces and fields between classes. They are similar to Java 8's interfaces. Classes and objects can extend traits.Missing: delegation | Show results with:delegation
  32. [32]
    5 Type Classes and Overloading - Haskell.org
    In Haskell, type classes provide a structured way to control ad hoc polymorphism, or overloading. Let's start with a simple, but important, example: equality.Missing: delegation pattern
  33. [33]
    What is a C++ delegate? - Stack Overflow
    Mar 5, 2012 · There are many limitations of function pointers in C++. A delegate uses some behind-the-scenes template nastyness to create a template-class ...C++ 11 Delegated Constructor Pure Virtual Method & Function CallsEvolution of delegates [closed] - Stack OverflowMore results from stackoverflow.comMissing: early | Show results with:early