Шаблон делегирования

В разработке ПО, шаблон делегирования (англ. delegation pattern) — это способ, которым объект внешне выражает некоторое поведение, но в реальности передаёт ответственность за выполнение этого поведения связанному объекту в Inversion of Responsibility. Шаблон делегирования является фундаментальной абстракцией которая поддерживает композицию (также называемую агрегацией), примеси (mixins) и аспекты (aspects).

Содержание

Примеры

Простой пример на Java

В этом примере на языке Java, класс C имеет метод-затычку (method stub), который передаёт методы f() и g() классу A. Класс C делает вид, что он имеет атрибуты класса A.

class A {
    void f() { System.out.println("A: doing f()"); }
    void g() { System.out.println("A: doing g()"); }
}

class C {
    // delegation
    A a = new A();

    void f() { a.f(); }
    void g() { a.g(); }

    // normal attributes
    X x = new X();
    void y() { /* do stuff */ }
}

public class Main {
    public static void main(String args) {
        C c = new C();
        c.f();
        c.g();
    }
}

Сложный пример на Java

Используя интерфейсы, делегирование может быть осуществлено более гибко и c защитой типов (typesafe). В этом примере, класс C может делегировать либо классу A либо классу B. Класс C имеет методы для переключения между классами A и B. Включение расширения implements улучшает безопасность типа, потому что каждый класс должен выполнять методы в интерфейсе. Основным недостатком является большее количество кода.

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 {
    // delegation
    I i = new A();

    public void f() { i.f(); }
    public void g() { i.g(); }

    // normal attributes
    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();
    }
}

Сложный пример на C++

Этот пример — это версия на C++ сложного примера на Java, приведённого выше. Так как C++ не имеет конструкции интерфейса, ту же самую роль играет чистый виртуальный класс. Преимущества и недостатки в основном те же самые, что и в примере на Java.

#include <iostream>
using namespace std;

class I {
  public:
    virtual void f() = 0;
    virtual void g() = 0;
};

class A : public I {
  public:
    void f() { cout << "A: doing f()" << endl; }
    void g() { cout << "A: doing g()" << endl; }
};

class B : public I {
  public:
    void f() { cout << "B: doing f()" << endl; }
    void g() { cout << "B: doing g()" << endl; }
};

class C : public I {
  public:
    // construction/destruction
    C() : i( new A() ) { }
    virtual ~C() { delete i; }

  private:
    // delegation
    I* i;

  public:
    void f() { i->f(); }
    void g() { i->g(); }

    // normal attributes
    void toA() { delete i; i = new A(); }
    void toB() { delete i; i = new B(); }
};

int main() {
    C* c = new C();

    c->f();
    c->g();
    c->toB();
    c->f();
    c->g();
}

Критика

Этот паттерн обычно уничтожает оптимизацию по скорости в пользу улучшенной чистоты абстракции.

См. также

 
Начальная страница  » 
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 Home