
//Target: a pointer to a function plays Request()
typedef struct CText {
void (*getText)(const struct CText *self, char *buffer, size_t size);
} CText;
//Adaptee
typedef struct {
const char *rows[10];
size_t count;
} StringList;
void add(StringList *list, const char *value) {
if (list->count < 10) {
list->rows[list->count++] = value;
}
}
//SpecificRequest()
void getString(const StringList *list, char *buffer, size_t size) {
buffer[0] = '\0';
for (size_t i = 0; i < list->count; i++) {
if (i != 0) {
strncat(buffer, "\n", size - strlen(buffer) - 1);
}
strncat(buffer, list->rows[i], size - strlen(buffer) - 1);
}
}
//Adapter: the target is the first field, the adaptee is
//an object it points to
typedef struct {
CText base;
const StringList *rowList;
} TextAdapter;
//Request() passes the work to SpecificRequest()
void adapterGetText(const CText *self, char *buffer, size_t size) {
const TextAdapter *adapter = (const TextAdapter *)self;
getString(adapter->rowList, buffer, size);
}
//Client
StringList rowList = {};
add(&rowList, "line 1");
add(&rowList, "line 2");
//the adapter wraps a list that already exists
TextAdapter adapter = {{adapterGetText}, &rowList};
CText *target = &adapter.base;
char text[32];
target->getText(target, text, sizeof text);
//text: line 1
// line 2
printf("text:\n%s\n", text);
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.Read more问题。程序通过一个方法从任意来源读取文本。系统的另一部分提供现成的行列表。列表能把自己的各行拼接起来,但用的是另一个名字的方法。这些列表送来时已经填好,它们的类也无法修改。调用程序所期望方法的代码,也不想改动。 思路。适配器让一个已有的类,即被适配者,符合客户端所期望的接口,即目标接口。在这个版本中,适配器实现目标接口,并持有一个被适配者对象的引用。它的目标方法把调用转发给这个对象,有时做一点小小的转换。适配器没有被适配者的其他方法。可以与继承方式的适配器对照:后者继承被适配者,而不是持有它。 如何阅读示例。示例中有两个对象:被适配者,以及持有它的适配器。在大多数语言中,被适配者单独创建,再交给适配器。在少数语言中,适配器自己创建被适配者,客户端通过适配器的字段来填充它。客户端只通过目标方法读取结果,适配器把这个调用转发给被适配者。有些适配器在没有持有被适配者时返回空结果。在某些语言中,适配器只是一个捕获了被适配者的函数。 何时使用。在大多数情况下,优先选择对象适配器。它能适配被适配者类型的任何对象,包括子类的对象和已经存在的对象。如果可以直接修改被适配者,就根本不要使用适配器:给一个方法改名代价更小。 常见错误。把新的逻辑放进适配器。适配器只负责把一种调用翻译成另一种调用。检查和业务规则应放在别处。 |