Как обрабатывать ссылку «это» в шаблоне декоратора - PullRequest
5 голосов
/ 13 октября 2010

У меня проблема в моем классе, который использует шаблон декоратора.

Проблема возникает, когда внутренний объект использует ссылку "this" в вызовах других объектов.Это приводит к тому, что все вызовы от объекта, который получил ссылку «this», будут сделаны непосредственно на внутренний объект, не проходя сначала внешний.

Как обычно решить эту проблему?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 13 октября 2010

Объекты имеют неявное значение: их идентичность (можно проверить, применив ==). Когда вы оборачиваете их, вы фактически скрываете эту идентичность (что еще хуже, вы также выставляете потенциально вводящую в заблуждение идентичность, идентичность самой оболочки). Таким образом, очевидный подход компенсирует это, раскрывая идентичность объекта другим способом - явно. Например. Вы можете ввести метод Object getIdentity(), который возвращает объект, действительно представляющий предполагаемую идентичность, и позволяющий применять к нему ==.

Огромным недостатком является то, что вы по-прежнему допускаете == на самом декораторе, например опасность, что:

  • достаточно естественно, чтобы его обманули (identity == decorator вместо identity == decorator.getIdentity())
  • молча делает неправильные вещи (сравните с исключением времени выполнения - удачи при отладке)

Проблема не существовала бы, если бы, например, у объектов был такой метод:

protected Object getIdentity() {
    return this;
}

Для которого будет определен оператор ==, поэтому оболочка может также обернуть идентификатор обернутого объекта вместо его замены своим собственным.

1 голос
/ 13 октября 2010

То, что вы описываете, представляет собой смесь шаблонов декоратора и шаблона.Шаблон декоратора позволяет вам динамически добавлять поведение к объекту (используя прокси-подобный механизм).Шаблон шаблона разбивает алгоритм на несколько методов, поэтому вы можете изменять поведение объекта, подставляя методы с помощью подклассов или, в вашем случае, декоратора.

Поскольку декораторы являются типом прокси, они содержат ссылку нацелевой объект (или другой декоратор, обернутый n-слоями глубоко вокруг целевого объекта).Но цель обычно не отслеживает свои декораторы и не делает никаких предположений относительно декораторов.

Так что каждый раз, когда поведение целевого объекта изменяется путем добавления или удаления самого внешнего декоратора, ваш дизайн должен будет либо обновить целевой объект с помощьюссылка на его самый внешний декоратор или целевой объект должен будет запросить другой объект для ссылки на самый внешний декоратор.

Если целевой объект может запросить ссылку на декорированный стек объектов из любого объекта, ответственного за его удержание (что-то должно), значит, ты, наверное, в порядке.В противном случае целевому объекту может потребоваться обратиться к делегату или посреднику.

1 голос
/ 13 октября 2010

В общем, вы не можете. Если вы не создадите подкласс для своего декорированного класса, ваш внутренний класс будет свободен для вызова любого метода, использующего себя в качестве параметра, и изменить его невозможно.

При использовании шаблона декоратора класс декоратора отвечает за передачу ссылки this (ссылаясь на сам декоратор) на другие методы. С моей точки зрения, декоратор наиболее похож на прокси-сервер: внутренний декорированный объект полностью обернут в свои декораторы и не доступен напрямую. Таким образом, вы должны сами найти способ запретить вашему украшенному объекту прямой доступ к другим объектам и возможность передавать this reference

...