Delegation (patrón de diseño)
En Ingeniería de software, el patrón de diseño de delegación es una técnica en la que un objeto de cara al exterior expresa cierto comportamiento pero en realidad delega la responsabilidad de implementar dicho comportamiento a un objeto asociado en una relación inversa de responsabilidad.
El patrón de diseño de Delegación es la abstracción fundamental que da soporte a la composición (también referida como agregación), los mixin y los aspectos.
Ejemplos
[editar]En este ejemplo realizado en el lenguaje de programación Java, la clase C
tiene métodos "cabecera" (método stub) que realizan llamadas a los métodos f()
y g()
de la clase A
class A {
void f() { System.out.println("A: haciendo f()"); }
void g() { System.out.println("A: haciendo g()"); }
}
class C {
// objeto asociado para delegacion
A a = new A();
void f() { a.f(); }
void g() { a.g(); }
// atributos normales
X x = new X();
void y() { /* haz algo */ }
}
public class Main {
public static void main(String[] args) {
C c = new C();
c.f();
c.g();
}
}
Ejemplo complejo en Java
[editar]Utilizando interfaces Java, la delegación puede hacerse de manera más flexible y fuertemente tipada. En este ejemplo, la clase C
puede delegar bien en la clase A
o en la clase B
. La clase C
tiene métodos para conmutar entre las clases A
y B
. Utilizando la cláusula implements
se asegura la fortaleza de tipos porque cada clase debe implementar los métodos definidos en la interfaz. La principal contrapartida es que se añade más código.
interface I {
void f();
void g();
}
class A implements I {
public void f() { System.out.println("A: haciendo f()"); }
public void g() { System.out.println("A: haciendo g()"); }
}
class B implements I {
public void f() { System.out.println("B: haciendo f()"); }
public void g() { System.out.println("B: haciendo g()"); }
}
class C implements I {
// objeto asociado de delegacion
I i = new A();
public void f() { i.f(); }
public void g() { i.g(); }
// atributos normales
void toA() { i = new A(); }
void toB() { i = new B(); }
}
public class Main {
public static void main(String[] args) {
C c = new C();
c.f();
c.g();
c.toB();
c.f();
c.g();
}
}
Ejemplo complejo en C++
[editar]Este ejemplo es una versión en C++ del ejemplo complejo escrito en Java anterior. Puesto que C++ no tiene interfaces propiamente dichas, una clase abstracta realiza el mismo juego. Las ventajas y desventajas son principalmente las mismas que en el ejemplo en Java.
#include <iostream>
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: haciendo f()" << endl; }
void g() { cout << "A: haciendo g()" << endl; }
~A() { cout << "A: llamada al destructor." << endl; }
};
class B : public I {
public:
void f() { cout << "B: haciendo f()" << endl; }
void g() { cout << "B: haciendo g()" << endl; }
~B() { cout << "B: llamada al destructor." << endl; }
};
class C : public I {
public:
// constructor/destructor
C() : i( new A() ) { }
virtual ~C() { delete i; }
private:
// Interfaz de delegacion
I* i;
public:
void f() { i->f(); }
void g() { i->g(); }
// atributos normales
void toA() { delete i; i = new A(); }
void toB() { delete i; i = new B(); }
};
int main() {
C* c = new C();
c->f(); // A: haciendo f()
c->g(); // A: haciendo g()
c->toB(); // A: llamada al destructor.
c->f(); // B: haciendo f()
c->g(); // B: haciendo g()
delete c; // B: llamada al destructor.
}
Delegate reemplazado por la composición
[editar]Los beneficios que se obtienen con delegate son los mismos que se pueden obtener con la composición y uso de interfaces en lenguajes orientados a objetos.[1]
Referencias
[editar]- ↑ «Facade & Delegate en nuestras arquitecturas de software - La Filosofia del Software». 21 de mayo de 2023. Consultado el 22 de mayo de 2023.