文章目录
1、场景举例
笔记本充电:
我们的笔记本电压一般是24V,但是在中国标准电压是220V,在日本标准电压是110V。要让不同标准的电压给笔记本充电,中间就需要一个适配器,能将220V或者110V电压转为24V。
2、主要应用场景
1、使用一个已经存在的类,如果它的接口和你实际要求的不一致时,可以考虑使用适配器模式
2、要在调用者和功能提供者双方都不太容易修改的时候再使用适配器模式,而不是一有不同时就使用它
3、类图
类适配器
上图是适配器模式的第一种实现形式,适配器Adapter继承自Target和Adaptee类,Adapter类需要重写Target类的Request函数,在Request中做适当的处理,调用Adaptee类的SepcificRequest。最终,Target实际调用的是Adaptee的SpecificRequest来完成Request的,完成适配;这种叫做类适配器。
对象适配器
上图是适配器的第二种实现形式,适配器Adapter类继承自Target类,同时,在Adapter类中有一个Adaptee类型的成员变量;Adapter类重写Request函数时,在Request中,使用Adaptee类型的成员变量调用Adaptee的SpecificRequest函数,最终完成适配;这种叫做对象适配器。
4、用C语言实现适配器模式
角色定义
1、适配器
2、被适配者
案例描述
使用适配器模式时间打印 hello world
案例实现
#include <stdio.h>
#include <stdlib.h>
typedef struct ADAPTEE{
void (*request)(void);
}Adaptee;
typedef struct ADAPTER{
struct ADAPTEE *adaptee;
void (*request)(struct ADAPTER *);
}Adapter;
void request(void)
{
printf("I'm here!!!\n");
return;
}
void request_adapter(struct ADAPTER *adapter)
{
adapter->adaptee->request();
return;
}
void *apply_memory(char *str)
{
struct ADAPTER *adapter = NULL;
struct ADAPTEE *adaptee = NULL;
void *tmp = NULL;
if (!strcmp(str,"ADAPTER")){
adapter = (struct ADAPTER *)malloc(sizeof(struct ADAPTER));
if (adapter == NULL){
return NULL;
}
adapter->request = request_adapter;
tmp = (void *)adapter;
}else if (!strcmp(str,"ADAPTEE")){
adaptee = (struct ADAPTEE *)malloc(sizeof(struct ADAPTEE));
if (adaptee == NULL){
return NULL;
}
adaptee->request = request;
tmp = (void *)adaptee;
}
return tmp;
}
int main()
{
struct ADAPTER *adapter = NULL;
struct ADAPTEE *adaptee = NULL;
adapter = (struct ADAPTER *)apply_memory("ADAPTER");
adaptee = (struct ADAPTEE *)apply_memory("ADAPTEE");
adapter->adaptee = adaptee;
adapter->request(adapter);
if (adapter != NULL){
free(adapter);
}
if (adaptee != NULL){
free(adaptee);
}
return 0;
}
5、用C++实现适配器模式(类适配器)
角色定义
1、确定目标接口
2、确定被适配者
3、创建适配器(继承自被适配者,实现目标接口)
案例描述
使用类适配器完成打印hello world
案例实现
#include <iostream>
using namespace std;
class TARGET{
public:
virtual void request() = 0;
};
class ADAPTEE{
public:
void appoint_request(){
cout << "hello! I'm here!!!" << endl;
}
};
class ADAPTER:public TARGET,public ADAPTEE{
public:
void request(){
ADAPTEE::appoint_request();
}
};
int main()
{
TARGET *target = new ADAPTER();
target->request();
if (target == NULL){
delete target;
target == NULL;
}
return 0;
}
6、用C++实现适配器模式(对象适配器)
角色定义
1、确定目标接口
2、确定被适配者
3、创建适配器(拥有被适配者的对象,实现目标接口)
案例描述
使用对象适配器,实现打印hello world!
案例实现
#include <iostream>
using namespace std;
class TARGET{
public:
virtual void request() = 0;
};
class ADAPTEE{
public:
void target_request(){
cout << "hello,I'm here!!!" << endl;
}
};
class ADAPTER:public TARGET{
public:
ADAPTER():m_adaptee(new ADAPTEE()){};
~ADAPTER(){
if (m_adaptee != NULL){
delete m_adaptee;
m_adaptee = NULL;
}
}
void request(){
m_adaptee->target_request();
}
private:
ADAPTEE *m_adaptee;
};
int main()
{
TARGET *obj_target = new ADAPTER();
obj_target->request();
if (obj_target != NULL){
delete obj_target;
}
return 0;
}
7、类适配器和对象适配器特点
类适配器
1、由于Adapter直接继承自Adaptee类,所以,在Adapter类中可以对Adaptee类的方法进行重定义;
2、如果在Adaptee中添加了一个抽象方法,那么Adapter也要进行相应的改动,这样就带来高耦合;
3、如果Adaptee还有其它子类,而在Adapter中想调用Adaptee其它子类的方法时,使用类适配器是无法做到的。
对象适配器
1、有的时候,你会发现,不是很容易去构造一个Adaptee类型的对象;
2、当Adaptee中添加新的抽象方法时,Adapter类不需要做任何调整,也能正确的进行动作;
3、可以使用多态的方式在Adapter类中调用Adaptee类子类的方法。
由于对象适配器的耦合度比较低,所以在很多的书中都建议使用对象适配器。在我们实际项目中,也是如此,能使用对象组合的方式,就不使用多继承的方式