我曾尝试将此代码转换为对象适配器,但由于我仍在尝试完全理解这一点,因此没有找到正确的方法。
这是我在C++中找到的唯一的适配器代码,而其他代码通常并不完整,只显示了适配器部分,所以我也发现很难编写自己的代码。
网站上的其他答案也无济于事。如果有人能在Object Adapter中重写它,并向我解释到底有什么不同,我将非常感激
#include <iostream>
using namespace std;
typedef int Coordinate;
typedef int Dimension;
// Desired interface
class Rectangle
{
public:
virtual void draw() = 0;
};
// Legacy component
class LegacyRectangle
{
public:
LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2)
{
x1_ = x1;
y1_ = y1;
x2_ = x2;
y2_ = y2;
cout << "LegacyRectangle: create. (" << x1_ << "," << y1_ << ") => ("<< x2_ << "," << y2_ << ")" << endl;
}
void oldDraw()
{
cout << "LegacyRectangle: oldDraw. (" << x1_ << "," << y1_ <<
") => (" << x2_ << "," << y2_ << ")" << endl;
}
private:
Coordinate x1_;
Coordinate y1_;
Coordinate x2_;
Coordinate y2_;
};
// Adapter wrapper
class RectangleAdapter: public Rectangle, private LegacyRectangle
{
public:
RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h):
LegacyRectangle(x, y, x + w, y + h)
{
cout << "RectangleAdapter: create. (" << x << "," << y <<
"), width = " << w << ", height = " << h << endl;
}
virtual void draw()
{
cout << "RectangleAdapter: draw." << endl;
oldDraw();
}
};
int main()
{
Rectangle *r = new RectangleAdapter(120, 200, 60, 40);
r->draw();
}发布于 2017-04-25 14:50:34
RectangleAdapter和LegacyRectangle的关系应该是"has-a“,而不是"is-a”。
class RectangleAdapter: public Rectangle
{
public:
RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h):
legacyRectangle(x, y, x + w, y + h)
{
cout << "RectangleAdapter: create. (" << x << "," << y <<
"), width = " << w << ", height = " << h << endl;
}
virtual void draw()
{
cout << "RectangleAdapter: draw." << endl;
legacyRectangle.oldDraw();
}
private:
LegacyRectangle legacyRectangle;
};注意:我没有测试它
发布于 2017-04-25 16:16:25
这是我在C++中找到的唯一的适配器代码,而其他代码通常不完整,只显示了适配器部分,所以我也发现很难编写自己的代码。
嗯,它工作得很好……
...我还在试着完全理解这一点。
所以我认为详细解释这个例子会有所帮助……
需要此类适配器类问题通常是,您希望将某些遗留代码集成或使用到您自己的API中,但您不能或不想修改这些遗留coce。该方案的一个变体是一起使用两个不同且不兼容的API。
现在的想法是提供一个适配器/包装器类,它将一个API的对象“转换”为另一个API的对象(让我们继续讨论遗留场景,然后将一个遗留API对象转换为您自己的API对象)。
如果您现在使用组合或私有继承(组合更可取,请参阅sithereal答案的注释中的链接),这并不是真正的重点。重要的是,您的适配器/包装器类以某种合适的方式合并了遗留对象,以便它可以访问所需的任何内容。
基本思想是,适配器将使用遗留类提供的功能来模拟成为基类。
返回到示例:
class Rectangle;抽象基类。它定义了任何矩形类应该提供的接口(在这种情况下:draw函数,它是纯虚拟的,即没有实现)。您自己的类-让我们称其为OrdinaryRectangle (没有更好的想法-自己发明一些东西...)-将简单地继承自Rectangle基类并根据需要实现绘制函数。
按照这个例子,你将以同样的方式定义你自己的接口,并提供一个实现--或者你已经实现了。您可能已经完成了自己的类的实现,但可能还需要将公共接口提取到新的基类中。好的,慢慢地……
class LegacyRectangle;来自其他/遗留API的类。您可能会从遗留API中获取的实例,并在以后将它们反馈给。将这些实例转换成你自己的API然后再转换回来(例如,通过在矩形和类型转换运算符中提供适当的构造函数)--这是另一种选择--由于任何原因(运行时开销、编码工作等)可能都太昂贵了。因此,您包装了另一个类,假装是您自己的rectangle实现的一个实例,但在内部使用了遗留的rectangle。
class RectangleAdapter : public Rectangle, private LegacyRectangle好吧,这个例子使用了私有继承,所以我会继续,尽管在另一个答案中有所有的讨论……
从矩形公开继承(就像(必须!)为了能够像处理OrdinaryRectangle一样处理RectanlgeAdapter (从技术上讲是错误的:更好:两者都继承自Rectangle,两者都可以被视为这样--不管你实际拥有哪个实例--在大多数情况下,你甚至不知道!),OrdinaryRectangle也是必需的。
私有地从LegacyRectangle继承(或者最好拥有的内部成员)为您提供了遗留应用程序接口对象的内部实例。
构造函数;很好,我将省略这一个来解释...但是:您可能想要为LegacyRectangle添加复制和移动构造函数(通常,这些术语用于复制/移动您自己的类的实例--但您会看到)--这是特别的(仅限?)有趣的是,如果LegacyRectangle本身提供了这样的构造函数(虽然是在经典意义上):
RectangleAdapter(LegacyRectangle const& lr) : LegacyRectangle(lr) { }
RectangleAdapter(LegacyRectangle&& lr) : LegacyRectangle(std::move(lr)) { }(以上是不完整的,但应该足以说明!)
virtual void draw()
{
cout << "RectangleAdapter: draw." << endl;
oldDraw();
}这里我们是核心--我们通过使用遗留API来实现我们自己的API的接口。在本例中,这非常简单--我们只使用oldDraw()函数。在现实中,这可以实现任意的复杂性。再深入一点:想象一下没有oldDraw,而是drawBorder和fillInterior函数。然后,您必须在自己的draw函数中使用这些函数。
这就是它变得非常困难的地方。如果你在那里有问题,你需要得到更具体的,然后我们需要知道确切的szenario(s)和详细的问题,以便能够帮助你……在此之前先看一下how to ask a good question和how to create a mcve。
https://stackoverflow.com/questions/43603440
复制相似问题