更多设计模式参看: 设计模式之模式概述(模式汇总)(C++实现)
适配器模式(Adapter Pattern): 将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。
两种实现如何选择。以下可做参考:
判断的标准主要有两个,一个是 Adaptee 接口的个数,另一个是 Adaptee 和 ITarget 的契合程度。
如果 Adaptee 接口并不多,那两种实现方式都可以。
如果 Adaptee 接口很多,而且 Adaptee 和 ITarget 接口定义大部分都相同,那推荐使用类适配器,因为 Adaptor 复用父类 Adaptee 的接口,比起对象适配器的实现方式,Adaptor 的代码量要少一些。
如果 Adaptee 接口很多,而且 Adaptee 和 ITarget 接口定义大部分都不相同,那推荐使用对象适配器,因为组合结构相对于继承更加灵活。
适配器继承或依赖已有的对象,实现想要的目标接口。
封装有缺陷的接口设计
外部系统在接口设计方面有缺陷,引入之后会影响到自身代码,为了隔离设计上的缺陷可以使用适配器模式抽象出更好的接口设计
统一多个类的接口设计
某个功能的实现依赖多个外部系统(或者说类)。通过适配器模式,将它们的接口适配为统一的接口定义,然后我们就可以使用多态的特性来复用代码逻辑。比如统一多款第三方敏感词过滤系统的接口。
替换依赖的外部系统
当我们把项目中依赖的一个外部系统替换为另一个外部系统的时候,利用适配器模式,可以减少对代码的改动。
兼容老版本接口
在做版本升级的时候,对于一些要废弃的接口,不直接将其删除,而是暂时保留,并且标注为 deprecated,并在内部委托为新的接口实现。
适配不同格式的数据
还可以用在不同格式的数据之间的适配。比如,把收集的不同存储格式的数据,统一为相同的格式,以方便存储和使用。
读卡器、电源适配器等各种转接头
JAVA 中的 jdbc
(1) 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
(2) 增加了类的透明性和复用性,对于客户端类而言是透明的,同一个适配者类可以在多个不同的系统中复用。
(3) 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
敏感词过滤
类适配器:
ClassAdapter
对象适配器:
Objectadapter
/// Target(目标抽象类)
class FilterTarget {
public:
virtual ~FilterTarget() = default;
virtual void filter(std::string text) = 0;
protected:
FilterTarget() = default;
};
/// Adaptee(适配者类)
class FilterAdaptee_A {
public:
FilterAdaptee_A() {
std::cout << "FilterAdaptee_A Hello" << std::endl;
type = "FilterAdaptee_A";
}
~FilterAdaptee_A() {
std::cout << "FilterAdaptee_A Bye" << std::endl;
}
void adapteeFilter(const char *text) {
std::cout <<"过滤器为:" << type << std::endl;
std::cout <<"过滤内容为:" << text << std::endl;
}
private:
std::string type;
};
class FilterAdaptee_B {
public:
FilterAdaptee_B() {
std::cout << "FilterAdaptee_B Hello" << std::endl;
type = "FilterAdaptee_B";
}
~FilterAdaptee_B() {
std::cout << "FilterAdaptee_B Bye" << std::endl;
}
void adapteeFilter(const std::string& text, const std::string& mask) {
std::cout <<"过滤器为:" << type << std::endl;
std::cout <<"过滤内容为:" << text << std::endl;
std::cout <<"过滤mask为:" << mask << std::endl;
}
private:
std::string type;
};
类适配器:
/// Adapter(适配器类)
class FilterAdapter_A: public FilterTarget, private FilterAdaptee_A {
public:
FilterAdapter_A() {
std::cout << "Class FilterAdapter_A Hello" << std::endl;
}
~FilterAdapter_A() override {
std::cout << "Class FilterAdapter_A Bye" << std::endl;
}
void filter(const std::string text) override {
const char *temp = text.c_str();
adapteeFilter(temp);
}
};
class FilterAdapter_B: public FilterTarget, private FilterAdaptee_B {
public:
FilterAdapter_B() {
std::cout << "Class FilterAdapter_B Hello" << std::endl;
mask = "MASK_B";
}
~FilterAdapter_B() override {
std::cout << "Class FilterAdapter_B Bye" << std::endl;
}
void filter(const std::string text) override {
adapteeFilter(text,mask);
}
private:
std::string mask;
};
对象适配器:
/// Adapter(适配器类)
class FilterAdapter_A: public FilterTarget {
public:
FilterAdapter_A() {
std::cout << "Object FilterAdapter_A Hello" << std::endl;
}
~FilterAdapter_A() override {
std::cout << "Object FilterAdapter_A Bye" << std::endl;
}
void filter(const std::string text) override {
const char *temp = text.c_str();
filterAdapteeA.adapteeFilter(temp); // 委托
}
private:
FilterAdaptee_A filterAdapteeA;
};
class FilterAdapter_B: public FilterTarget {
public:
FilterAdapter_B() {
std::cout << "Object FilterAdapter_B Hello" << std::endl;
mask = "MASK_B";
}
~FilterAdapter_B() override {
std::cout << "Object FilterAdapter_B Bye" << std::endl;
}
void filter(const std::string text) override {
filterAdapteeB.adapteeFilter(text,mask);
}
private:
FilterAdaptee_B filterAdapteeB;
std::string mask;
};
int main() {
std::list<FilterTarget *> filterList;
filterList.push_back(new FilterAdapter_A());
filterList.push_back(new FilterAdapter_B());
std::list<FilterTarget *>::iterator iter; //声明一个迭代器
iter = filterList.begin();
while (iter!=filterList.end()) {
FilterTarget * filter = *iter++;
filter->filter("this is a Adapter Design Pattern Demo");
}
while(!filterList.empty()) {
FilterTarget * filter = filterList.front();
filterList.pop_front();
delete filter;
}
return 0;
}
个人能力有限,如有错误之处或者其他建议,敬请告知欢迎探讨,谢谢!