Delegation pattern

In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object. There is an Inversion of Responsibility in which a helper object, known as a delegate, is given the responsibility to execute a task for the delegator. The delegation pattern is one of the fundamental abstraction patterns that underlie other software patterns such as composition (also referred to as aggregation), mixins and aspects.

Examples

Java examples

Simple

In this Java example, the Printer

class has a print
method. This print method, rather than performing the print itself, delegates to class RealPrinter

. To the outside world it appears that the Printer

class is doing the print, but the RealPrinterclass is the one actually doing the work.

Delegation is simply passing a duty off to someone/something else. Here is a simple example:

 class RealPrinter {	// the "delegate"
	void print() { 
		System.out.println("something"); 
	}
 }
 
 class Printer {	// the "delegator"
	RealPrinter p = new RealPrinter();	// create the delegate 
	void print() { 
		p.print();	// delegation
	} 
 }
 
 public class Main {
	// to the outside world it looks like Printer actually prints.
	public static void main(String[] arguments) {
		Printer printer = new Printer();
		printer.print();
	}
 }

Complex

The more complex case is a Decorator Pattern that by using interfaces, delegation can be made more flexible and typesafe. "Flexibility" here means that C

need not refer to A
or B
in any way, as the switching of delegation is abstracted from C

. In this example, class C

can delegate to any class that implements I

. Class C

has a method to switch to another delegator. Including the implementsclauses improves type safety, because each class must implement the methods in the interface. The main tradeoff is more code.
interface I {
	void f();
	void g();
}
 
class A implements I {
	public void f() { System.out.println("A: doing f()"); }
	public void g() { System.out.println("A: doing g()"); }
}
 
class B implements I {
	public void f() { System.out.println("B: doing f()"); }
	public void g() { System.out.println("B: doing g()"); }
}
 
class C implements I {
	I i = null;
	// delegation
	public C(I i){ setI(i); }
	public void f() { i.f(); }
	public void g() { i.g(); }
 
	// normal attributes
	public void setI(I i) { this.i = i; }
}
 
public class Main {
	public static void main(String[] arguments) {
		C c = new C(new A());
		c.f();	// output: A: doing f()
		c.g();	// output: A: doing g()
		c.setI(new B());
		c.f();	// output: B: doing f()
		c.g();	// output: B: doing g()
	}
}

C# example

This is a C# example of the complex Java example above.

public interface I
{
	void F();
	void G();
}
 
public class A : I
{
	public void F() { System.Console.WriteLine("A: doing F()"); }
	public void G() { System.Console.WriteLine("A: doing G()"); }
}
 
public class B : I
{
	public void F() { System.Console.WriteLine("B: doing F()"); }
	public void G() { System.Console.WriteLine("B: doing G()"); }
}
 
public class C : I
{
	// delegation
	I i = new A();
 
	public void F() { i.F(); }
	public void G() { i.G(); }
 
	// normal attributes
	public void ToA() { i = new A(); }
	public void ToB() { i = new B(); }
}
 
public class Program
{
	public static void Main()
	{
		C c = new C();
		c.F();	// output: A: doing F()
		c.G();	// output: A: doing G()
		c.ToB();
		c.F();	// output: B: doing F()
		c.G();	// output: B: doing G()
	}
}

C++ example (complex)

This example is a C++ version of the complex Java example above. Since C++ does not have an interface construct, a pure virtual class plays the same role. The advantages and disadvantages are largely the same as in the Java example.

#include <iostream>
#include <memory>
using namespace std;
 
class I {
  public:
	virtual void f() = 0;
	virtual void g() = 0;
	virtual ~I() {}
};
 
class A : public I {
  public:
	void f() { cout << "A: doing f()" << endl; }
	void g() { cout << "A: doing g()" << endl; }
	~A() { cout << "A: cleaning up." << endl; }
};
 
class B : public I {
  public:
	void f() { cout << "B: doing f()" << endl; }
	void g() { cout << "B: doing g()" << endl; }
	~B() { cout << "B: cleaning up." << endl; }
};
 
class C : public I {
  public:
	// construction/destruction
	C() : i( new A() ) { }
	virtual ~C() { }
 
  private:
	// delegation
	shared_ptr<I> i;
 
  public:
	void f() { i->f(); }
	void g() { i->g(); }
 
	// normal attributes
	void toA() { i.reset(new A()); }
	void toB() { i.reset(new B()); }
};
 
int main() {
	C c;
	c.f();  	//A: doing f()
	c.g();  	//A: doing g()
	c.toB();	//A: cleaning up.
	c.f();  	//B: doing f()
	c.g();  	//B: doing g()
}

Eiffel example (complex)

This example is an Eiffel version of the complex Java example above.

deferred class I feature
	f deferred end
	g deferred end
end
 
class A inherit I feature
	f do print("A: doing f%N") end
	g do print("A: doing g%N") end
end
 
class B inherit I feature
	f do print("B: doing f%N") end
	g do print("B: doing g%N") end
end
 
class C inherit I creation to_a, to_b feature
	i: I
 
	f do i.f end
	g do i.g end
 
	to_a do create {A} i end
	to_b do create {B} i end
end
 
class MAIN creation main feature
	main 
		local
			c: C 
		do
			create c.to_a
			c.f
			c.g
			c.to_b
			c.f
			c.g
		end
end

Objective-C example

Delegation is very common in the Cocoa framework. The following example is an Objective-C version of the complex Java example above.

@protocol I <NSObject>
- (void)f;
- (void)g;
@end
 
@interface A : NSObject <I>
@end
 
@implementation A
- (void)f { 
	NSLog(@"A: doing f"); 
}
- (void)g { 
	NSLog(@"A: doing g"); 
}
@end
 
@interface B : NSObject <I>
@end
 
@implementation B
- (void)f { 
	NSLog(@"B: doing f"); 
}
- (void)g { 
	NSLog(@"B: doing g"); 
}
@end
 
@interface C : NSObject <I>
 
@property (weak, nonatomic) id<I> i;	// delegation
 
- (void)toA;
- (void)toB;
 
@end
 
@implementation C
- (void)f { 
	[self.i f];
}
- (void)g { 
	[self.i g];
}
 
- (void)toA { 
	self.i = [[A alloc] init]; 
}
- (void)toB {
	self.i = [[B alloc] init]; 
}
 
// constructor
- (instancetype)init {
	if (self = [super init]) {
		_i = [[A alloc] init]; 
	}
	return self;
}
 
@end
 
int main (int argc, char *argv[]) {
	@autoreleasepool {
		C *c = [[C alloc] init];
		[c f];	// output: A: doing f
		[c g];	// output: A: doing g
		[c toB];
		[c f];	// output: B: doing f
		[c g];	// output: B: doing g
		return 0;
	}
}

Perl

use strict;
use warnings;
use 5.010_000;
 
package Example::Printer::Delegate::Role;
use Moose::Role;
 
=for comment
 Roles are like interfaces in other languages
   but are more powerful.
=cut
 
requires 'print_string';	# 'print_string' is required.
 
=for optional_methods
 
greet
 
=cut
 
package Example::Printer::Delegate::A;
use Moose;
with 'Example::Printer::Delegate::Role';
 
sub print_string {
	say 'Printed from A';
}
 
package Example::Printer::Delegate::B;
use Moose;
with 'Example::Printer::Delegate::Role';
 
sub print_string {
	say 'Printed from B';
}
 
sub greet {
	say 'And a hello to you!';
}
 
package Example::Printer;
use Moose;
 
has delegate => (
	is		=> 'rw',
	does		=> 'Example::Printer::Delegate::Role',
	predicate => 'hasDelegate'
);
 
sub print {
	my $self = shift;
 
	# Check to see, if I have a delegate
	if ( $self->hasDelegate ) {
		my $delegate = $self->delegate;
 
		# Call the delegate's print method. The role assures me that 
		#  print_string exists.
		$delegate->print_string;
 
		# Let's check to see if the delegate supports the greet method.
		if ( $delegate->can('greet') ) {
			# It does so, let's also greet people!
			$delegate->greet();
		}
	} else {
		warn 'No delegate!';
	}
}
 
package main;
use strict;
 
my $delegateA = Example::Printer::Delegate::A->new();
my $delegateB = Example::Printer::Delegate::B->new();
my $printer   = Example::Printer->new();
 
$printer->print();  # Will get a warning about not having a delegate.
 
say 'Setting delegate to Delegate A';
$printer->delegate($delegateA);
$printer->print();	# This will call $a's print_string method.
 
say 'Setting delegate to Delegate B';
$printer->delegate($delegateB);
$printer->print();	# This will call $b's print_string, and greet methods.

PHP

<?php
 
// Interface for printers.
interface iPrinter {
 
	// 'print' is a reserved word.
	public function printIt($subject);
}
 
// LinePrinter Printer Delegate
class LinePrinter implements iPrinter {
 
	public function printIt($line) {
 
		print $line;
		print "\n";
	}
}
 
// ArrayPrinter Printer Delegate
class ArrayPrinter implements iPrinter {
 
	public function printIt(array $array) {
		print_r($array);
	}
}
 
// Custom object.
class MyObject {
 
	protected $printer;
 
	public function __construct() {
 
		// Set delegate.
		$this->printer = new LinePrinter;
	}
 
	public function printData() {
 
		$this->printer->printIt('Some string data');
	}
}
 
// Another custom object
class MyOtherObject {
 
	protected $printer;
 
	public function __construct() {
 
		// Set delegate.
		$this->printer = new ArrayPrinter;
	}
 
	public function printData() {
 
		$this->printer->printIt(array(1,2,3));
	}
}
 
// ...
 
// Run it.
$object = new MyObject;
$object->printData();
 
// Run it.
$object = new MyOtherObject;
$object->printData();

Python Example (complex)

class I(object):
	def f(self): pass
	def g(self): pass
 
class A(I):
	def f(self):
		print "A: doing f()"
 
	def g(self):
		print "A: doing g()"
 
class B(I):
	def f(self):
		print "B: doing f()"
 
	def g(self):
		print "B: doing g()"
 
class C(I):
	def __init__(self):
		# delegation
		self.i = A()
 
	def f(self):
		self.i.f()
 
	def g(self):
		self.i.g()
 
	# normal attributes
	def to_a(self):
		self.i = A()
 
	def to_b(self):
		self.i = B()
 
if __name__ == '__main__':
	c = C()
	c.f() # output: A: doing f()
	c.g() # output: A: doing g()
	c.to_b()
	c.f() # output: B: doing f()
	c.g() # output: B: doing g()

Ruby example (complex)

module I
  def f
	puts "#{self.class}: doing f()"
  end
 
  def g
	puts "#{self.class}: doing g()"
  end
end
 
 
class A
  include I
end
 
 
class B
  include I
end
 
 
class C
  attr_accessor :i
  delegate :f, :g, :to => :i
 
  def initialize(klass = A)
	self.i = klass.new
  end
end
 
c = C.new
c.f		# output: A: doing f()
c.g		# output: A: doing g()
c = C.new(B)
c.f		# output: B: doing f()
c.g		# output: B: doing g()

Scala example

trait Thingable {
	def thing(): String
}
 
class Delegator {
	var delegate: Option[Thingable] = None
 
	def operation(): String = delegate match {
		case Some(t) => t.thing()
		case None => "default implementation"
	}
}
 
class Delegate extends Thingable {
	def thing(): String = "delegate implementation"
}
 
object DelegateExample {
	def main(arguments: Array[String]): Unit = {
		// Without a delegate:
		val a = new Delegator()
		assert(a.operation() == "default implementation")
 
		// With a delegate:
		val d = new Delegate()
		a.delegate = Some(d)
		assert(a.operation() == "delegate implementation")
 
		// Same as above, but with an anonymous class:
		a.delegate = Some(new Thingable {
			def thing(): String = "anonymous delegate implementation"
		})
		assert(a.operation() == "anonymous delegate implementation")
	}
}

Swift (complex)

protocol I {
	func f()
	func g()
}
 
class A : I {
	func f() {
		println("A doing F")
	}
	func g() {
		println("A doing G")
	}
}
 
class B : I {
	func f() {
		println("B doing F")
	}
	func g() {
		println("B doing G")
	}
}
 
class C : I {
	var i : I
 
	init() {
		i = A()
	}
 
	func f() {
		i.f()
	}
 
	func g() {
		i.g()
	}
 
	func toA() {
		i = A()
	}
 
	func toB() {
		i = B()
	}
}
 
let c = C()
c.f()  	//output  "A doing F"
c.g()  	//output  "A doing G"
c.toB()
c.f()  	//output  "B doing F"
c.g()  	//output  "B doing G"

Tcl

#TclOO is part of Tcl in 8.6 addon package in 8.5  
if { [ catch {package require TclOO } err ] != 0 } {
	puts stderr "Unable to find package TclOO ... adjust your auto_path!";
}
 
oo::class create I {
	constructor {} {
	}
 
	method f { } {puts "Error please implement"; };
	method g { } {puts "Error please implement"; }; 
}
 
oo::class create A {
	superclass I
 
	constructor {} {
	next;
	}
 
	method f { } {
		puts "A : doing f()"
	}
 
	method g { } {
		puts "A : doing g()"
	}
}
 
oo::class create B {
	superclass I 
 
	constructor {} {
	next;
	}
 
	method f { } {
		puts "B : doing f()"
	}
 
	method g { } {
		puts "B : doing g()"
	}
}
 
oo::class create C {
	variable i
 
	constructor {} {
		# delegation
		set i [A new ]
	}
 
	method f { } {
		$i f
	}
 
	method g { } {
		$i g 
	} 

	# normal attributes
	method to_a { } {
		$i destroy;
	set i [A new ]
	}
 
	method to_b { } {
		$i destroy;
	set i [B new ]
	}
}
 
set c [C new ]
$c to_a
$c f   ; # output A : doing f
$c g   ; # output A : doing g
$c to_b
$c f   ; # output B : doing f
$c g   ; # output B : doing g

See also

External links