适配器模式
Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
(将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。)
通用类图
目标类,把其他类转换为何种接口,期望接口。
适配源类,想把哪个类转换成目标类,其中那个类就是适配源类,也就是原始类,经过包装转换成目标类。
适配器类,需要新建的类,继承目标类和适配源类,使得目标类和适配源类产生关系。
通用源码
//目标类接口
class Target {
public:
virtual void request() = 0;
};
//目标类的实现类
class ConcreteTarget : public Target {
public:
virtual void request() {
//逻辑实现
}
};
//适配源类
class Adaptee {
public:
void doSomething() {
//逻辑实现
}
};
//适配器类
class Adapter : public Adaptee, public Target {
public:
virtual void request() {
Adaptee::doSomething();
}
};
优点
让两个没有任何关系的类在一起运行
增加类的透明性,实现对高层次透明
提高类的复用性
灵活性非常好
使用场景
修改已经投产中的接口时,适配器模式可以考虑
适配器模式是一个补偿模式,或者说是一个补救模式
注意事项
在详细设计阶段不需要考虑,不是解决处在开发阶段的最好方案。一定要遵守依赖倒置原则和里氏替换原则
扩展
上面的介绍是通过继承进行的适配,叫做类适配器
对象适配器,通过对象的合成关系,也可以说是类的关联关系。
对象适配器是用过类间的关联关系进行耦合的,在设计时比较灵活。
示例代码
#include <iostream>
#include <string>
#include <map>
using namespace std;
class IUserInfo{
public:
virtual string getUserName() = 0;
virtual string getHomeAddress() = 0;
virtual string getMobileNumber() = 0;
virtual string getOfficeTelNumber() = 0;
virtual string getJobPosition() = 0;
virtual string getHomeTelNumber() = 0;
};
class UserInfo : public IUserInfo {
public:
virtual string getUserName() {
cout << "NAME" << endl;
string name = "NAME";
return name;
}
virtual string getHomeAddress() {
cout << "HOMEADDR" << endl;
string res = "HOMEADDR";
return res;
}
virtual string getMobileNumber() {
cout << "MOBLENUM" << endl;
string res = "MOBLENUM";
return res;
}
virtual string getOfficeTelNumber() {
cout << "OFFICETEL" << endl;
string res = "OFFICETEL";
return res;
}
virtual string getJobPosition() {
cout << "JOBPOS" << endl;
string res = "JOBPOS";
return res;
}
virtual string getHomeTelNumber() {
cout << "HOMETEL" << endl;
string res = "HOMETEL";
return res;
}
};
class IOuterUser {
public:
virtual map<string, string> getUserBaseInfo() = 0;
virtual map<string, string> getUserOfficeInfo() = 0;
virtual map<string, string> getUserHomeInfo() = 0;
};
class OuterUser : public IOuterUser {
public:
virtual map<string, string> getUserBaseInfo() {
map<string, string> baseinfo;
baseinfo["username"] = "name";
baseinfo["mobileNumber"] = "mobileNum";
return baseinfo;
}
virtual map<string, string> getUserOfficeInfo() {
map<string, string> offinfo;
offinfo["jobPosition"] = "jobPos";
offinfo["officeTelNumber"] = "officeTel";
return offinfo;
}
virtual map<string, string> getUserHomeInfo() {
map<string, string> homeinfo;
homeinfo["homeTelNumber"] = "homeTel";
homeinfo["homeAddress"] = "homeAddr";
return homeinfo;
}
};
class OuterUserInfo : public IUserInfo, public OuterUser {
private:
map<string, string> baseinfo = OuterUser::getUserBaseInfo();
map<string, string> offinfo = OuterUser::getUserOfficeInfo();
map<string, string> homeinfo = OuterUser::getUserHomeInfo();
public:
virtual string getUserName() {
cout << baseinfo["username"] << endl;
return baseinfo["username"];
}
virtual string getHomeAddress() {
cout << homeinfo["homeAddress"] << endl;
return homeinfo["homeAddress"];
}
virtual string getMobileNumber() {
cout << baseinfo["mobileNumber"] << endl;
return baseinfo["mobileNumber"];
}
virtual string getOfficeTelNumber() {
cout << offinfo["officeTelNumber"] << endl;
return offinfo["officeTelNumber"];
}
virtual string getJobPosition() {
cout << offinfo["jobPosition"] << endl;
return offinfo["jobPosition"];
}
virtual string getHomeTelNumber() {
cout << homeinfo["homeTel"] << endl;
return homeinfo["homeTel"];
}
};
int main() {
IUserInfo *y = new UserInfo();
y->getMobileNumber();
IUserInfo *y1 = new OuterUserInfo();
y1->getMobileNumber();
return 0;
}