我阅读了关于适配器模式的“四人帮”的设计模式。但是我在实施部分阅读了第 2.c 段关于可插入适配器使用参数化适配器的内容,但我无法理解,因为示例在 Smalltalk 中。任何人都可以通过 Java 或 C++ 为我解释详细信息吗?对不起,我的英语太差了。谢谢
2 回答
首先,我觉得有必要提醒一点,不要过于深入地使用模式,尤其是在 C++ 中(许多 C++ 程序员对设计模式的重视程度持怀疑态度)。
也就是说,我怀疑大多数使用 C++ 的人会使用书中讨论的方法。这本书讨论了一种混合类型方法,您可以从某个抽象类继承,该抽象类定义了您要委托的接口。在他们的示例中,您将根据一些抽象的 DisplayableObject 类编写一个 TreeDisplay 类,然后您将通过从 DisplayableObject 继承(可能是多个,希望是私有的)创建一些特定类型的 TreeDisplay。
我无法想象有人以这种方式编写 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
。
该示例由两个文件组成: