feat: Adapter
Implemented a demo for the Adapter.
This commit is contained in:
parent
751033f2e9
commit
c49faa4780
47
07_adapter.cpp
Normal file
47
07_adapter.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class Target {
|
||||||
|
string s;
|
||||||
|
public:
|
||||||
|
Target(string s) : s(s) {}
|
||||||
|
virtual ~Target() = default;
|
||||||
|
|
||||||
|
virtual void request(const string& contents) {
|
||||||
|
cout << s << " send request to server: " << contents << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Adaptee {
|
||||||
|
public:
|
||||||
|
int value;
|
||||||
|
Adaptee(int value) : value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Adapter : public Target {
|
||||||
|
shared_ptr<Adaptee> a;
|
||||||
|
public:
|
||||||
|
Adapter(shared_ptr<Adaptee> a) :
|
||||||
|
Target("User " + to_string(a->value)), a(a) {}
|
||||||
|
|
||||||
|
virtual void request(const string& contents) override {
|
||||||
|
cout << "Adapted request" << endl;
|
||||||
|
Target::request(contents);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
shared_ptr<Target> t = make_shared<Target>("User A");
|
||||||
|
t->request("Hello");
|
||||||
|
|
||||||
|
shared_ptr<Adaptee> adaptee = make_shared<Adaptee>(42);
|
||||||
|
// Obviously this is invalid.
|
||||||
|
// a->request();
|
||||||
|
|
||||||
|
// But it works with adapter.
|
||||||
|
shared_ptr<Target> adapter = make_shared<Adapter>(adaptee);
|
||||||
|
adapter->request("Bye");
|
||||||
|
}
|
||||||
10
notes.md
10
notes.md
@ -39,3 +39,13 @@
|
|||||||
有时需要在项目中创建副本,那么如何创建重复对象?很容易想到使用复制或赋值操作符,而不是普通的构造函数。但是这些方法没有多态性,如果很多子类需要复制就会有点麻烦。
|
有时需要在项目中创建副本,那么如何创建重复对象?很容易想到使用复制或赋值操作符,而不是普通的构造函数。但是这些方法没有多态性,如果很多子类需要复制就会有点麻烦。
|
||||||
|
|
||||||
解决方案也很简单,父类提供一种 `clone` 方法。这样客户端只需要调用 `clone` 方法,不需要知道这个类具体是什么。这种方法常配合对象注册表使用,通过维护一个原型缓存容器(如`map<string, Prototype*>`),根据名字/类型复制对象。
|
解决方案也很简单,父类提供一种 `clone` 方法。这样客户端只需要调用 `clone` 方法,不需要知道这个类具体是什么。这种方法常配合对象注册表使用,通过维护一个原型缓存容器(如`map<string, Prototype*>`),根据名字/类型复制对象。
|
||||||
|
|
||||||
|
## 适配器模式(Adapter)
|
||||||
|
|
||||||
|
在开发过程中,可能会遇到接口不兼容的情况。例如,类 `A` 有一个向服务器发送请求的接口,而类 `B` 也需要实现类似的功能,但它并不继承自 `A`,因此无法通过多态方式调用 `A` 的接口。
|
||||||
|
|
||||||
|
一种解决方法是让 `B` 继承 `A`,这是一个很推荐的做法,但是这样做并不总是可行的,特别是当 `B` 是由他人设计或无法修改时。此时,可以设计一个适配器类。
|
||||||
|
|
||||||
|
适配器类可以继承自 `A`,并将 `B` 作为构造参数。在构造过程中,适配器将 `B` 的接口转换为符合 `A` 的接口形式。这样,通过适配器,`B` 就可以像 `A` 一样调用接口,达到接口兼容的效果。考虑到适配性,比如希望这个适配器类还能适配其他的 `C`,`D` 等,可以让适配器类接受一个更普遍的共性作为构造参数。
|
||||||
|
|
||||||
|
需要注意的是,这种做法显然会使得代码复杂很多,条件允许的话,还是直接修改 `B` 类较好。
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user