首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类适配器到对象适配器

类适配器到对象适配器
EN

Stack Overflow用户
提问于 2017-04-25 14:42:00
回答 2查看 373关注 0票数 0

我曾尝试将此代码转换为对象适配器,但由于我仍在尝试完全理解这一点,因此没有找到正确的方法。

这是我在C++中找到的唯一的适配器代码,而其他代码通常并不完整,只显示了适配器部分,所以我也发现很难编写自己的代码。

网站上的其他答案也无济于事。如果有人能在Object Adapter中重写它,并向我解释到底有什么不同,我将非常感激

代码语言:javascript
复制
#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();
}
EN

回答 2

Stack Overflow用户

发布于 2017-04-25 14:50:34

RectangleAdapter和LegacyRectangle的关系应该是"has-a“,而不是"is-a”。

代码语言:javascript
复制
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;
};

注意:我没有测试它

票数 0
EN

Stack Overflow用户

发布于 2017-04-25 16:16:25

这是我在C++中找到的唯一的适配器代码,而其他代码通常不完整,只显示了适配器部分,所以我也发现很难编写自己的代码。

嗯,它工作得很好……

...我还在试着完全理解这一点。

所以我认为详细解释这个例子会有所帮助……

需要此类适配器类问题通常是,您希望将某些遗留代码集成或使用到您自己的API中,但您不能或不想修改这些遗留coce。该方案的一个变体是一起使用两个不同且不兼容的API。

现在的想法是提供一个适配器/包装器类,它将一个API的对象“转换”为另一个API的对象(让我们继续讨论遗留场景,然后将一个遗留API对象转换为您自己的API对象)。

如果您现在使用组合或私有继承(组合更可取,请参阅sithereal答案的注释中的链接),这并不是真正的重点。重要的是,您的适配器/包装器类以某种合适的方式合并了遗留对象,以便它可以访问所需的任何内容。

基本思想是,适配器将使用遗留类提供的功能来模拟成为基类。

返回到示例:

代码语言:javascript
复制
class Rectangle;

抽象基类。它定义了任何矩形类应该提供的接口(在这种情况下:draw函数,它是纯虚拟的,即没有实现)。您自己的类-让我们称其为OrdinaryRectangle (没有更好的想法-自己发明一些东西...)-将简单地继承自Rectangle基类并根据需要实现绘制函数。

按照这个例子,你将以同样的方式定义你自己的接口,并提供一个实现--或者你已经实现了。您可能已经完成了自己的类的实现,但可能还需要将公共接口提取到新的基类中。好的,慢慢地……

代码语言:javascript
复制
class LegacyRectangle;

来自其他/遗留API的类。您可能会从遗留API中获取的实例,并在以后将它们反馈给。将这些实例转换成你自己的API然后再转换回来(例如,通过在矩形和类型转换运算符中提供适当的构造函数)--这是另一种选择--由于任何原因(运行时开销、编码工作等)可能都太昂贵了。因此,您包装了另一个类,假装是您自己的rectangle实现的一个实例,但在内部使用了遗留的rectangle。

代码语言:javascript
复制
class RectangleAdapter : public Rectangle, private LegacyRectangle

好吧,这个例子使用了私有继承,所以我会继续,尽管在另一个答案中有所有的讨论……

从矩形公开继承(就像(必须!)为了能够像处理OrdinaryRectangle一样处理RectanlgeAdapter (从技术上讲是错误的:更好:两者都继承自Rectangle,两者都可以被视为这样--不管你实际拥有哪个实例--在大多数情况下,你甚至不知道!),OrdinaryRectangle也是必需的。

私有地从LegacyRectangle继承(或者最好拥有的内部成员)为您提供了遗留应用程序接口对象的内部实例。

构造函数;很好,我将省略这一个来解释...但是:您可能想要为LegacyRectangle添加复制和移动构造函数(通常,这些术语用于复制/移动您自己的类的实例--但您会看到)--这是特别的(仅限?)有趣的是,如果LegacyRectangle本身提供了这样的构造函数(虽然是在经典意义上):

代码语言:javascript
复制
RectangleAdapter(LegacyRectangle const& lr) : LegacyRectangle(lr) { }
RectangleAdapter(LegacyRectangle&& lr) : LegacyRectangle(std::move(lr)) { }

(以上是不完整的,但应该足以说明!)

代码语言:javascript
复制
virtual void draw()
{
    cout << "RectangleAdapter: draw." << endl;
    oldDraw();
}

这里我们是核心--我们通过使用遗留API来实现我们自己的API的接口。在本例中,这非常简单--我们只使用oldDraw()函数。在现实中,这可以实现任意的复杂性。再深入一点:想象一下没有oldDraw,而是drawBorderfillInterior函数。然后,您必须在自己的draw函数中使用这些函数。

这就是它变得非常困难的地方。如果你在那里有问题,你需要得到更具体的,然后我们需要知道确切的szenario(s)和详细的问题,以便能够帮助你……在此之前先看一下how to ask a good questionhow to create a mcve

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43603440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档