适配器模式:将一个类的接口转换成客户希望的另外一个接口
需求
实现火箭队的比赛,教练叫暂停时给后卫、中锋、前锋分配进攻和防守任务的代码。还能通过翻译给不懂语言的外籍球员指令。
代码
业务类
c
#include <stdio.h>
#include <stdlib.h>
typedef struct Player {
char *name;
void (*attack)(struct Player *);
void (*defense)(struct Player *);
} Player;
// 前锋
typedef struct Forward {
Player base;
} Forward;
typedef struct Center {
Player base;
} Center;
typedef struct Guard {
Player base;
} Guard;
void ForwardAttack(Player *obj) {
printf("前锋 %s 进攻\n", obj->name);
}
void ForwardDefense(Player *obj) {
printf("前锋 %s 防守\n", obj->name);
}
void CenterAttack(Player *obj) {
printf("中锋 %s 进攻\n", obj->name);
}
void CenterDefense(Player *obj) {
printf("中锋 %s 防守\n", obj->name);
}
void GuardAttack(Player *obj) {
printf("后卫 %s 进攻\n", obj->name);
}
void GuardDefense(Player *obj) {
printf("后卫 %s 防守\n", obj->name);
}
Forward *InitForward(char *name) {
Forward *obj = (Forward *)malloc(sizeof(Forward));
obj->base.name = name;
obj->base.attack = ForwardAttack;
obj->base.defense = ForwardDefense;
return obj;
}
Center *InitCenter(char *name) {
Center *obj = (Center *)malloc(sizeof(Center));
obj->base.name = name;
obj->base.attack = CenterAttack;
obj->base.defense = CenterDefense;
return obj;
}
Guard *InitGuard(char *name) {
Guard *obj = (Guard *)malloc(sizeof(Guard));
obj->base.name = name;
obj->base.attack = GuardAttack;
obj->base.defense = GuardDefense;
return obj;
}
typedef struct ForeignCenter {
char *name;
void (*jingong)(struct ForeignCenter *);
void (*fangshou)(struct ForeignCenter *);
} ForeignCenter;
void ForeignCenterAttack(ForeignCenter *obj) {
printf("中锋 %s 进攻\n", obj->name);
}
void ForeignCenterDefense(ForeignCenter *obj) {
printf("中锋 %s 防守\n", obj->name);
}
ForeignCenter *InitForeignCenter(char *name) {
ForeignCenter *obj = (ForeignCenter *)malloc(sizeof(ForeignCenter));
obj->name = name;
obj->jingong = ForeignCenterAttack;
obj->fangshou = ForeignCenterDefense;
return obj;
}
适配器类
将外籍球员的jingong,fangshou借口转换为attack,defense接口。
c
typedef struct Translator {
Player base;
ForeignCenter *fc;
} Translator;
void TranslatorAttack(Player *obj) {
((Translator *)obj)->fc->jingong(((Translator *)obj)->fc);
}
void TranslatorDefense(Player *obj) {
((Translator *)obj)->fc->fangshou(((Translator *)obj)->fc);
}
Translator *InitTranslator(char *name, char *fcName) {
Translator *obj = (Translator *)malloc(sizeof(Translator));
obj->base.name = name;
obj->base.attack = TranslatorAttack;
obj->base.defense = TranslatorDefense;
obj->fc = InitForeignCenter(fcName);
return obj;
}
客户端
c
int main() {
Forward *kuli = InitForward("kuli");
kuli->base.attack((Player *)kuli);
Translator *xiaotiancai = InitTranslator("xiaotiancai", "yaoming");
xiaotiancai->base.attack((Player *)xiaotiancai);
return 0;
}
UML图

总结
- 适配器使用场景?
想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。即两个类所做的事情相同或相似,但是具有不同的接口时要使用它。使客户代码可以统一调用同一接口。但注意要在双方都不太容易修改的时候再使用适配器模式适配,而不是一有不同时就使用它。