提问人:Source 提问时间:10/27/2023 更新时间:10/28/2023 访问量:88
C 语言中的设计模式适配器
Design Pattern Adapter in C
问:
定义:
适配器是一种结构设计模式,它允许具有 不兼容的协作接口。
我必须使用不兼容的回调函数指针,第一个参数有所不同。
我们知道对象有键值对,数组有索引值对。char * 与 int。
void object_callback(char *key, void *value) {
printf("%d: %s\n", index, value);
}
void array_callback(int index, void *value) {
printf("%d: %s\n", index, value);
}
用例
void process_object(void (*callback)(char *key, void *value)) {
// callback if key-value-based properties
callback(key, value);
// callback for array-based properties
callback((int)key, value); // trying to implement adapter pattern for this
}
我本来可以使用,但正在寻找一个基于适配器设计模式的优雅解决方案。void *
我的尝试
#include <stdio.h>
typedef struct Adapter {
void (*obj)(char *key, void *value);
void (*arr)(int index, void *value);
} Adapter;
void property_callback(char *key, void *value) {
printf("%s: %s\n", key, value);
}
void array_callback(int index, void *value) {
printf("%d: %s\n", index, value);
}
答:
1赞
Cem Polat
10/27/2023
#1
您需要创建一个适配器函数,该函数将弥合两个不同回调接口之间的差距。下面是将适配器函数与不同回调一起使用的简单示例。
#include <stdio.h>
// Define the original callback functions
void objectCallback(char *key, void *value) {
printf("%s: %s\n", key, (char*)value);
}
void arrayCallback(int index, void *value) {
printf("%d: %s\n", index, (char*)value);
}
// Adapter structure to encapsulate the original callbacks
typedef struct {
void (*callback)(void* keyOrIndex, void *value);
} Adapter;
// Adapter function for objectCallback
void objectAdapter(void* key, void *value) {
objectCallback((char*)key, value);
}
// Adapter function for arrayCallback
void arrayAdapter(void* key, void *value) {
int idx = (int)(long)key; // Cast void pointer to int
arrayCallback(idx, value);
}
int main() {
// Create an adapter for objectCallback
Adapter objectAdapterInstance = {objectAdapter};
// Create an adapter for arrayCallback
Adapter arrayAdapterInstance = {arrayAdapter};
// Demonstrate the use of the adapters
char* k = "property_key";
char* v = "property_value";
// Use the object adapter
objectAdapterInstance.callback(k, v);
// Use the array adapter
int i = 123;
arrayAdapterInstance.callback((void*)(long)i, v);
return 0;
}
评论
0赞
Source
11/21/2023
我意识到最好的方法是使用单个方法,检查是否要调用数组版本,如果不是,则调用另一个对象版本。void *
isdigit
0赞
Lundin
10/27/2023
#2
如果第一个参数没有,那么在编译时,您可以简单地使用该参数来区分这两种用途:void*
#include <stdio.h>
void object_callback(char *key, void *value) {
printf("%s: %s\n", key, (char*)value);
}
void array_callback(int index, void *value) {
printf("%d: %s\n", index, (char*)value);
}
#define callback(a, b) \
_Generic((a), \
char*: object_callback, \
int: array_callback \
) (a,b)
int main (void)
{
callback("hello", "world");
callback(123, "world");
}
评论
0赞
Lundin
10/27/2023
这里需要注意的是,避免使用函数指针通常会导致更快的代码。具有函数指针的解决方案不太可能被编译器内联,这意味着开销执行时间。而我上面的代码很容易被编译器归结为两个 printf 调用。
0赞
Michael Walsh Pedersen
10/28/2023
#3
两种解决方案:
解决方案 1:删除回调函数指针的参数列表:
#include <stdio.h>
void property_callback(char *key, void *value) {
printf("%s: %s\n", key, (char*)value);
}
void array_callback(int index, void *value) {
printf("%d: %s\n", index, (char*)value);
}
void process_object( void (*callback)(),
int functype, char *key, int index, void *value)
{
if(functype==1) callback(key, value);
if(functype==2) callback(index, value);
}
int main()
{
process_object(property_callback , 1, "key", 123 , "value" );
process_object(array_callback , 2, "key", 123 , "value" );
return 0;
}
解决方案 2:使用回调指针的并集:
#include <stdio.h>
void property_callback(char *key, void *value) {
printf("%s: %s\n", key, (char*)value);
}
void array_callback(int index, void *value) {
printf("%d: %s\n", index, (char*)value);
}
typedef union {
void (*prop)(char *key, void *value);
void (*arr)(int index, void *value);
} cbtype;
void process_object( cbtype callback,
int functype, char *key, int index, void *value)
{
if(functype==1) callback.prop(key, value);
if(functype==2) callback.arr(index, value);
}
int main()
{
process_object( (cbtype){.prop=property_callback} , 1, "key", 123 , "value" );
process_object( (cbtype){.arr=array_callback} , 2, "key", 123 , "value" );
return 0;
}
评论
object_callback
index
object_callback
index