Я прочитал «Шаблон дизайна» «Банды четырех» о шаблоне адаптера. Но я читаю в разделе Реализация, параграф 2.c, рассказывает о подключаемых адаптерах, использующих параметризованные адаптеры, но я не могу понять, потому что пример находится в Smalltalk. Кто-нибудь может объяснить детали для меня с помощью Java или C ++? Извините, мой английский такой плохой. Спасибо
Во-первых, я чувствую себя обязанным немного предостеречь от тоже глубоко в использовании шаблонов, особенно в C ++ (многие программисты на C ++ придают особое значение шаблонам проектирования со степенью скептицизма).
Тем не менее, я сомневаюсь, что большинство людей, использующих C ++, будут использовать подход, обсужденный в книге. В книге обсуждается подход смешанного типа, в котором вы наследуете какой-то абстрактный класс, определяющий интерфейс, которому вы делегируете. В их примере у вас будет класс TreeDisplay, написанный в терминах некоторого абстрактного класса DisplayableObject, а затем вы создадите некоторый конкретный тип TreeDisplay с помощью (возможно, множественного, мы надеемся, частного) наследования от DisplayableObject.
Я не могу себе представить, чтобы кто-нибудь писал C ++ таким образом, кроме как в существующем проекте, который уже использовал эту архитектуру. Если бы кто-то писал новый C ++ для реализации этого, он почти наверняка сделал бы TreeDisplay шаблоном, а DisplayableObject — параметром шаблона.
template <class DisplayableObject>
class TreeDisplay {
DisplayableObject const &root;
public:
TreeDisplay(DisplayableObject const &d) : root(d) {}
display(graphic const *g);
void build_tree(DisplayableObject const &d=root) {
for (auto child : d.get_children) {
add_node(d.CreateGraphicNode(this, child));
build_tree(child); // recursively add child's children
}
}
}
Тогда отображаемый объект будет иметь что-то вроде:
class DirectoryBrowser {
std::vector<directory> children;
public:
std::vector<directory> &get_children() { return children; }
void CreateGraphicNode(TreeDisplay *t, directory const &d) {
t->display(d.name);
}
};
Это, безусловно, делает не соответствуют реализации, обсуждаемой в книге, но, как я уже сказал выше, я не могу себе представить, чтобы кто-нибудь писал сегодня C ++ так, как обсуждается в книге. Кроме того, я сомневаюсь, что многие из них напрямую вернут ссылку на внутренние данные DirectoryBrowser — это просто быстрый и грязный способ продемонстрировать генеральный идея.
Насколько все это должно быть достигнуто: в основном разделение. TreeDisplay знает, как отображать элементы в дереве, но ему не нужно знать подробности об отдельных объектах в дереве. И наоборот, элементы, отображаемые в дереве, не должны ничего знать о том, что отображение является деревом. Если вы решите отображать те же самые элементы в плоском списке, это не будет иметь никакого значения для DirectoryBrowser (или другого отображаемого объекта). Он просто должен знать, как отправить отображаемую версию себя обратно в функцию, когда его об этом попросят.
Короче говоря, мы минимизировали интерфейс между ними, так что любой из них может быть изменен без минимального влияния на другой, и это настолько просто, насколько это возможно, реализовать различные варианты любого и заставить его работать со всеми существующими реализациями другой части.
Я предполагаю, что в Java большинство программистов определят интерфейс DisplayableObject (возможно, под другим именем) и используют его в качестве точки «вставки», чтобы TreeDisplay взаимодействовал с объектами в дереве. В то время как дженерики Java, вероятно, мог Я использую для этого, я не вижу такой же вероятности, как использование шаблонов в C ++ (по причинам, в основном не связанным с рассматриваемым вопросом).
Вот это дополнительный пример шаблона адаптера, но в Java. Пример кода в нижней части этой страницы демонстрирует, как легко адаптироваться LinkedList
реализация к Queue
интерфейс.
Пример состоит из двух файлов: