Delegation pattern

From Wikipedia, the free encyclopedia

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 RealPrinter class 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[] args) {
         Printer printer = new Printer();
         printer.print();
     }
 }

Complex

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 implements clauses 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){ this.i = i; }
    public void f() { i.f(); }
    public void g() { i.g(); }
 
    // normal attributes
    public void to(I i) { this.i = i; }
}
 
public class Main {
    public static void main(String[] args) {
        C c = new C(new A());
        c.f();     // output: A: doing f()
        c.g();     // output: A: doing g()
        c.to(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(args: 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")
	}
}

See also

External links

This article is issued from Wikipedia. The text is available under the Creative Commons Attribution/Share Alike; additional terms may apply for the media files.