Adapter(适配器)模式总结


前言

        本周五参加了Adapter(适配器)模式研讨会,本文的目的是对这个模式的总结和分享,希望对需要学习这个设计模式的同学有所帮助。本文一共分为两个部分,第一个部分是适配器模式的基础知识总结;第二个部分是使用适配器模式的一个例子分享。

一、适配器模式总结

         适配器模式有两种子模式:类适配器和对象适配器,这两种子模式的意图是一致的,参与者是一致的,只是结构不同,效果有差异。类适配器采用继承的方式适配Adaptee,而对象适配器采用的是聚合方式适配Adaptee。

1、模式意图

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得接口不兼容的类可以一起工作。

2、参与者

Target
-- 定义Client使用的接口。
Client
-- 与Target接口对象协同。
Adaptee
-- 需要适配的,已经存在的接口
Adapter
-- 对Adaptee和Target接口进行适配。

3、类适配器结构及效果

类适配器结构图:

在这里插入图片描述

效果:

1、使用一个具体的Adapter类对Adaptee和Target进行匹配,这使得不能匹配具体Adapter的子类。
2、可以使Adapter可以重定义Adaptee的部分行为。
3、仅仅引入了一个对象,并不需要额外的指向Adaptee的指针。

4、对象适配器结构及效果

对象适配器的结构图:

在这里插入图片描述

效果:
1、允许一个Adapter与多个Adaptee(及其子类对象)协同工作。
2、使得重定义Adaptee的行为比较困难。


二、对象适配器C语言用例

1、用例背景描述

         在can总线中,我们总是希望把总线上接收到的帧保存到文件当中,方便对接收到的数据进行解析和分析。保存的文件格式是CSV、ASC等可视化的文件格式,由于客户的需求不断变化,记录数据的文件格式除了CSV、ASC外,还需要支持BLF格式文件。blf格式是一种加密文件,已经有现成的库,提供了操作blf文件接口。我们的文件记录模块需要支持blf文件,重新实现blf的逻辑是不现实的,因为我们不知道文件的结构,但是利用已有的库是可以实现blf存储的,这就需要我们对blf库进行封装,增加一个适配器,适配blf接口和统一文件存储接口。通过适配,我们存储blf可以和CSV等格式保持一致。

2、用例结构图

在这里插入图片描述

3、用例Target类

         这里我们仅展示需要用到的公共接口,其他接口,例如构造和析构等接口省略。

struct file_operation_t;
typedef ret_t (*open_file_t)(file_operation_t *file_operation, const char *file_name, bool_t is_save);

typedef ret_t (*close_file_t)(file_operation_t *file_operation);

typedef char*  (*read_data_t)(file_operation_t *file_operation);

typedef ret_t  (*write_data_t)(file_operation_t *file_operation, const char *data);

typedef struct _file_operation_vtable_t {
	open_file_t open;
	close_file_t close;
	read_data_t read;
	write_data_t write;
} file_operation_vtable_t;

typedef struct _file_operation_t {
  char *file_name;
  void *file_handle;
  int offset;
  file_operation_vtable_t *vt;
} file_operation_t;

file_operation_t *file_operation_create();


// 实现

static const file_operation_vtable_t s_file_operation_vtable = {
.open = NULL,
.close = NULL,
.read = NULL;
.write = NULL;
};


file_operation_t *file_operation_create() {
	file_operation_t *obj = (file_operation_t *)malloc(sizeof(file_operation_t));
	obj->vt = &s_file_operation_vtable;
	return obj;
}

4、用例Adaptee接口

         blf接口也提供了能完成Target功能的接口。
//创建文件,对应open_file
void *BlCreateFile(const char *file_name, int open_type);
//关闭文件,对应close_file
bool_t BLCloseHandle(void *handle);
//读文件,对应read_data
char* BlReadObject(void *handle);
//写文件,对应write_data
int BlWriteObject(void *handle, const char *data);

5、用例Adapter类定义

         这个例子中,我们只能采用对象适配器模式来实现适配器,因为我们没办法继承一个库来实现类适配器,只能通过对象的方式来适配已有的库功能。我们需要公有继承Target,然后在实现代码中应用Adaptee的接口来实现blf文件操作。
typedef struct _blf_file_operation_t {
  file_operation_t parent;
} blf_file_operation_t;

file_operation_t *blf_file_operation_create();

6、用例Adapter类实现

         通过blf库提供的接口实现blf文件的打开、关闭和读写。

static ret_t open_file(file_operation_t *file_operation, const char *file_name, bool_t is_save) {
	void *handle;
	return_value_if_fail(file_operation != NULL && file_name != NULL, RET_BAD_PARAMS);
	
	if (is_save) {
		handle = BlCreateFile(file_name, GENERIC_WRITE);
	} else {
		handle = BlCreateFile(file_name, GENERIC_READ);
	}
	
	file_operation->file_handle = handle;
	return RET_OK;
}

static ret_t close_file(file_operation_t *file_operation) {
	return_value_if_fail(file_operation != NULL, RET_BAD_PARAMS);
	BLCloseHandle(file_operation->file_handle);
	return RET_OK;
}

static char* read_data(file_operation_t *file_operation) {
	return_value_if_fail(file_operation != NULL, NULL);
	return BlReadObject(file_operation->file_handle);
}

static ret_t write_data(file_operation_t *file_operation, const char *data) {
	return_value_if_fail(file_operation != NULL && data != NULL, RET_BAD_PARAMS);
	return BlWriteObject(file_operation->file_handle, data);
}

static const file_operation_vtable_t s_blf_file_operation_vtable = {
.open = open_file,
.close = close_file,
.read = read_data;
.write = write_data;
};

file_operation_t *blf_file_operation_create() {
	file_operation_t *obj = (file_operation_t *)malloc(sizeof(blf_file_operation_t));
	obj->vt = &s_blf_file_operation_vtable;
	return obj;
}

7、用例Client

客户端代码接口只用基类指针,这样,客户就不必关心具体用的是哪一种文件格式了,接口都是统一的。

file_operation_t *get_file_operation_obj();

ret_t do_open(file_operation_t *file_operation, const char* file_name);
ret_t do_close(file_operation_t *file_operation);
...

//实现
ret_t do_open(file_operation_t *file_operation, const char* file_name) {
	return file_operation->vt->open(file_operation, file_name);
}

....

总结

         适配器模式的思想是把已经存在的功能,由于接口不兼容而不能一起工作时,增加一层包装,使得封装后的接口满足客户系统的需求。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值