Позвольте мне поделиться несколькими мыслями.
Во-первых, поскольку вопрос был опубликован с тегом Smalltalk, я буду использовать синтаксис Smalltalk, который является менее подробным (например, #children
вместо * 1004). *, et c.)
В качестве введения к этой проблеме (которая может быть полезна для некоторых читателей), скажем, что (generi c) фреймворки должны использовать язык c generi ( например, #children
). Однако общие термины c могут быть не естественными для указанного объекта c, который вы рассматриваете. Например, в случае файловой системы обычно используется #files
, #directories
и т. Д. c., Но может отсутствовать селектор #children
. Даже если добавление этих селекторов никого не убьет, вы не хотите заполнять свои классы новыми селекторами «generi c» каждый раз, когда «абстрактный» класс налагает свои соглашения об именах. В реальной жизни, если вы сделаете это, рано или поздно у вас возникнут коллизии с другими структурами, для которых тот же самый селектор имеет другое значение. Это подразумевает, что каждая структура имеет потенциал создания некоторого импеданса (т. Е. Трения) с объектами, которые пытаются извлечь из этого выгоду. Ну, адаптеры предназначены для смягчения этих побочных эффектов.
Есть несколько способов сделать это. Один делает ваш каркас подключаемый . Это означает, что вы не будете требовать от клиентов реализации определенного поведения c. Вместо этого вы попросите клиентов предоставить селектор или блок, вычисление которого приведет к требуемому поведению.
В примере Справочника, если ваш класс Справочник реализуется, скажем #entities
, тогда вместо создания #children
как синоним, вы скажете соответствующему классу в рамках что-то вроде childrenSelector: #entities
. Объект, получающий этот метод, затем «подключит» (помните), что он должен отправить вам #entities
при поиске children
. Если у вас нет такого метода, вы все равно можете обеспечить требуемое поведение, используя блок, который делает то, что нужно. В нашем примере блок будет выглядеть следующим образом:
childrenSelector: [self directories, self files].
( Примечание: сменная структура может предоставить синоним #childrenBlock:
, чтобы сделать его интерфейс более дружественным. В качестве альтернативы, он может обеспечить более общий селектор, такой как childrenGetter:
, et c.)
Теперь получатель будет хранить блок в childrenGetter
ivar и будет оценивать его каждый раз, когда ему нужны дочерние элементы клиента.
Другое решение, которое можно рассмотреть, состоит в том, чтобы потребовать от клиента подкласса абстрактного класса. Это имеет то преимущество, что очень четко показывает поведение клиента. Однако обратите внимание, что у этого решения есть некоторые недостатки, поскольку в Smalltalk вы можете наследовать только от одного родителя. Таким образом, введение суперкласса может привести к нежелательному (или даже невыполнимому) ограничению.
Другой вариант, который вы упоминаете, состоит в добавлении одного косвенного обращения к предыдущему: вместо подкласса основного «объекта» вы предлагаете реферат суперкласс для создания подкласса поведения, который ваш объект должен адаптировать. Это похоже на первый подход в том, что вам не нужно менять клиента, за исключением того, что на этот раз вы помещаете адаптированный протокол в класс самостоятельно. Таким образом, вместо вставки нескольких параметров в каркас, вы помещаете их все в объект и передаете (или «подключаете») этот объект в каркас. Обратите внимание, что эти приспосабливающиеся объекты действуют как обертки в том смысле, что они знают реальную вещь и знают, как с ней обращаться для перевода тех немногих сообщений, которые должна отправить инфраструктура. В общем, использование оболочек обеспечивает большую гибкость за счет заполнения вашей системы большим количеством классов (что влечет за собой риск дублирования иерархий). Кроме того, упаковка многих объектов может повлиять на производительность вашей системы. Заметьте, кстати, что GraphicNode
также выглядит как оболочка внутреннего / фактического Node
.
Я не уверен, что ответил на ваш вопрос, но так как вы попросили меня как-то расширить мой комментарий Я с радостью попробовал.