C - 客户端如何使用/访问多个实现?

标签 c coding-style refactoring

下图(图片)是Linux/net/socket.c源码的仿制方法。

Background:

Reason to implement List abstraction with this approach, is to make a working prototype before implementing snmp library, with same approach. f Inspired from Linux/net/socket.c, where any one of the protocol family implementations(like net/ipv4/af_inet.c or net/unix/af_unix.c/..) is available on invoking socket() interface api

Client invoking socket() api, avails any one protocol family implementation based on the argument(AF_INET | AF_UNIX | AF_XYZ) passed to socket() interface api.

enter image description here

上述方法中,list.h提供了List接口(interface),代码如下,

/********************** list.h ********************/


#ifndef LIST_H /* Header guard */
#define LIST_H
#include"type.h"

/****************** Interface - start  ********/

 typedef struct List List;
 typedef enum {ARRAY_IMPL, LINKED_LIST_IMPL}ImplType;


 typedef int (*compareTo)(const void *, const void *);
 typedef bool (*isLess)(const void *, const void *);
 typedef bool (*isEqual)(const void *, const void *);

 List* createList(ImplType);
  void freeList(List*);
  void swim(List*, int, isLess);
  void sink(List*, int, isLess);
const  void* deleteMax(List*, isLess);
const  void* sortDeleteMax(List*);
   int getSize(List*);
const void* getItem(List*, const int);
 List* sortInsertItem(List*, const void*, compareTo);
  void insertItem(List*, const void*);
const  void* deleteItem(List*, int);
const  void* deleteLastItem(List*);
const  void* deleteFirstItem(List*);
   int lSearch(const void*, List*, size_t, compareTo);
   int bSearch(const void*, List*, size_t, compareTo);
  void callInsertionSort(List*, size_t, isLess);
  void callMergeSort(List*, size_t, isLess);
  void swap(List*, int, int);
/****************** Interface - end  ********/
#endif

将实现(arrayImpl.o/linkListImpl.o)链接到可执行文件(a.out)发生在链接器阶段。

virtualImplLayer.c 根据传递给 createList()< 的参数 (ARRAY_IMPL | LINKED_LIST_IMPL) 选择任何 实现处理 接口(interface) api。此实现处理程序存储在 handler 全局变量中,如下所示。 接口(interface) api 的其余部分依赖于这个全局变量。

/*****************virtualImplLayer.c*************************/
#include "list/listHandler.h"

/*****Private symbol - start *****************/
static ListHandler * findListImplHandler(ImplType);
/*****Private symbol - end   *****************/


ListHandler *handler = NULL;
/***** User interface - start *************/
List* createList(ImplType implType){

  handler =  findListImplHandler(implType);

  if(handler != NULL){

    List *list = handler->createList();
    return list;
  }
  fprintf(stderr, "createList() - No implementation for this feature\n");
  return NULL;

}


void freeList(List *list){

    handler->freeList(list);
}


void swim(List *list, int parentIndex, isLess less){

    handler->swim(list, parentIndex, less);

}


void sink(List *list, int index, isLess less){

    handler->sink(list, index, less);
}


const void* deleteMax(List *list, isLess less){

    return handler->listDeleteMaxElement(list, less);
}


const void* sortDeleteMax(List *list){

    return handler->sortedListDeleteMaxElement(list);
}
int getSize(List *list){

    return handler->listGetSize(list);
}


const void* getItem(List *list, const int index){

    return handler->listGetItem(list, index);
}


List* sortInsertItem(List *list, const void *item, compareTo compare){

    return handler->sortedListInsertItem(list, item, compare);
}


void insertItem(List *list, const void *item){

    handler->listInsertItem(list, item);
}
const void* deleteItem(List *list, int listIndex){

    return handler->listDeleteItem(list, listIndex);
}


const void* deleteLastItem(List *list){

    return handler->listDeleteLastItem(list);
}


const void* deleteFirstItem(List *list){

    return handler->listDeleteFirstItem(list);
}


int lSearch(const void *key, List *list, size_t size, compareTo compare){

    return handler->linearSearch(key, list, size, compare);
}


int bSearch(const void *key, List *list, size_t size, compareTo compare){

    return handler->binarySearch(key, list, size, compare);
}
void callInsertionSort(List *list, size_t size, isLess less){

    handler->insertionSort(list, size, less);
}


void callMergeSort(List *list, size_t size, isLess less){

    handler->mergeSort(list, size, less);
}


void swap(List *list, int i, int j){

    handler->swap(list, i, j);
}

/***** User interface -end *************/

/*****Private symbol - start *****************/
static ListHandler * findListImplHandler(ImplType implType){

  ListHandler *implHandler = NULL;
  int handlerIndex = 0;
  while(listHandlers[handlerIndex] !=NULL){

    implHandler = listHandlers[handlerIndex];
    if( implHandler->canHandle(implType) ){
      return implHandler;
    }
    handlerIndex++;
  }
  return NULL;
}
/*****Private symbol - end *****************/

Linux/net/ipv4/af_inet.cLinux/net/unix/af_unix.c 等实现在加载阶段通过覆盖 _init( ) 执行中的运行时代码(比如af_inet.c),如下图,

static int __init inet_init(void){
  ....
  void)sock_register(&inet_family_ops);
  ....
}

问题来了,对于 virtualImplLayer.c 中的给定实现,客户端程序不能期望使用/访问多个实现(arrayImpl.c /LinkListImpl.c),因为 handler 变量被覆盖


完整的工作示例是 here给出编译说明here

问题:

ImplType 仅传递给 createList() 接口(interface),在 virtualImplLayer.c 中,如何避免覆盖全局变量 处理程序,以利用多个实现?

最佳答案

删除全局的唯一方法是在 List 本身中存储一些类型信息。

例如,您可以强制执行一个约定(通过考虑一点 OO,只要 C 有助于它)。两个 List 实现都必须包含以下 struct

作为第一个成员
struct ListRtti {
  ListHandler *handler_;
  // Other relevent meta data you may want
};

所以

struct List {
  ListRtti rtti_;

  // Implementation details
};

现在,您可以从指向对象本身的指针中检索处理程序。由于第一个成员的地址保证是整个对象的地址:

((ListRtti*)list)->handler_;

临:

  • 处理程序始终是一个间接的距离。
  • 用户可以根据自己的喜好混合和交换实现。

缺点:

  • 元数据需要为每个分配的对象额外存储。
  • Actor 阵容令人侧目。

关于C - 客户端如何使用/访问多个实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41593108/

相关文章:

C# 等效于 C++ 宏并使用 Auto<> 属性

language-agnostic - 函数的常见且合理的参数顺序是什么?

delphi - 初级 Delphi 开发人员应该学习哪些干净、优雅、设计良好、编写良好、做得很好的 Delphi 代码?

java - 用话说什么是重构参与者?

performance - 哪个更快?比较还是赋值?

C、rand 函数不能与 sleep() 函数一起正常工作

c - C 语言中的 OpenMP + MPI 混合 - 编译困难

c - mvwaddstr() 导致 McAfee 误报

c - 如何在 C 中舍入 Float 值

c++ - 用于 C++ 开发的 Refactor Pro 与 Visual Assist X