结构型设计模式之适配器模式
适配器模式
适配器模式有助于采用不同接口的对象之间的合作。 它的运作方式如下:
- 适配器实现与其中一个现有对象兼容的接口。
- 现有对象可以使用该接口安全地调用适配器方法。
- 适配器方法被调用后将以另一个对象兼容的格式和顺序将请求传递给该对象。
说明:文章插图与代码均引用自 refactoringguru.com 网站,但代码解释为原创中文翻译,转载请注明来源。
UML 示意图
C++ 代码实现
基础概念的实现
/**
* The Target defines the domain-specific interface used by the client code.
* Target 定义了客户端代码使用的特定领域的接口
*/
class Target {
public:
virtual ~Target() = default;
virtual std::string Request() const {
return "Target: The default target's behavior.";
}
};
/**
* The Adaptee contains some useful behavior, but its interface is incompatible
* with the existing client code. The Adaptee needs some adaptation before the
* client code can use it.
* Adaptee 有一些有用的行为,但是它的接口和已有客户端代码不匹配,
* 在客户端使用 Adaptee 前需要对它做一个适配。
*/
class Adaptee {
public:
std::string SpecificRequest() const {
return ".eetpadA eht fo roivaheb laicepS";
}
};
/**
* The Adapter makes the Adaptee's interface compatible with the Target's
* interface.
* Adapter 让 Adaptee 的接口和 Target 的接口相匹配
*/
class Adapter : public Target {
private:
Adaptee *adaptee_;
public:
Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
std::string Request() const override {
std::string to_reverse = this->adaptee_->SpecificRequest();
std::reverse(to_reverse.begin(), to_reverse.end());
return "Adapter: (TRANSLATED) " + to_reverse;
}
};
/**
* The client code supports all classes that follow the Target interface.
* 客户端代码里支持了所有遵从 Target 接口的类
*/
void ClientCode(const Target *target) {
std::cout << target->Request();
}
int main() {
std::cout << "Client: I can work just fine with the Target objects:\n";
// Client Code 和 Target 对象工作的很好
Target *target = new Target;
ClientCode(target);
std::cout << "\n\n";
//但是 Adaptee 的接口 Client Code 用不了
Adaptee *adaptee = new Adaptee;
std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
std::cout << "Adaptee: " << adaptee->SpecificRequest();
std::cout << "\n\n";
std::cout << "Client: But I can work with it via the Adapter:\n";
// Adapter 对象实例由 adaptee 的实例构造
//(能把相关成员和方法传入)
// 但是 Client Code 能够用 adater 对象实例,因为 adapter 继承了 Target
Adapter *adapter = new Adapter(adaptee);
ClientCode(adapter);
std::cout << "\n";
delete target;
delete adaptee;
delete adapter;
return 0;
}
执行结果
Client: I can work just fine with the Target objects:
Target: The default target's behavior.
Client: The Adaptee class has a weird interface. See, I don't understand it:
Adaptee: .eetpadA eht fo roivaheb laicepS
Client: But I can work with it via the Adapter:
Adapter: (TRANSLATED) Special behavior of the Adaptee.
多重继承的实现
/**
* The Target defines the domain-specific interface used by the client code.
* Target 定义了客户端代码使用的特定领域的接口
*/
class Target {
public:
virtual ~Target() = default;
virtual std::string Request() const {
return "Target: The default target's behavior.";
}
};
/**
* The Adaptee contains some useful behavior, but its interface is incompatible
* with the existing client code. The Adaptee needs some adaptation before the
* client code can use it.
* Adaptee 有一些有用的行为,但是它的接口和已有客户端代码不匹配,
* 在客户端使用 Adaptee 前需要对它做一个适配。
*/
class Adaptee {
public:
std::string SpecificRequest() const {
return ".eetpadA eht fo roivaheb laicepS";
}
};
/**
* The Adapter makes the Adaptee's interface compatible with the Target's
* interface using multiple inheritance.
* Adapter 让 Adaptee 的接口和 Target 的接口相匹配
* 多继承在某些情况下可以允许不用传递 adaptee 实例
*/
class Adapter : public Target, public Adaptee {
public:
Adapter() {}
std::string Request() const override {
std::string to_reverse = SpecificRequest();
std::reverse(to_reverse.begin(), to_reverse.end());
return "Adapter: (TRANSLATED) " + to_reverse;
}
};
/**
* The client code supports all classes that follow the Target interface.
*/
void ClientCode(const Target *target) {
std::cout << target->Request();
}
int main() {
std::cout << "Client: I can work just fine with the Target objects:\n";
Target *target = new Target;
ClientCode(target);
std::cout << "\n\n";
Adaptee *adaptee = new Adaptee;
std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
std::cout << "Adaptee: " << adaptee->SpecificRequest();
std::cout << "\n\n";
std::cout << "Client: But I can work with it via the Adapter:\n";
//多继承时,adapter 构造可以不用 adaptee 实例
Adapter *adapter = new Adapter;
ClientCode(adapter);
std::cout << "\n";
delete target;
delete adaptee;
delete adapter;
return 0;
}
运行结果
Client: I can work just fine with the Target objects:
Target: The default target's behavior.
Client: The Adaptee class has a weird interface. See, I don't understand it:
Adaptee: .eetpadA eht fo roivaheb laicepS
Client: But I can work with it via the Adapter:
Adapter: (TRANSLATED) Special behavior of the Adaptee.