0

我已经创建ColorBlockImageBlock抽象类的子Block类。 Block实现大小和位置,并有一个抽象方法draw()ColorBlock实现color属性并将自身绘制为一个彩色方块。 ImageBlock实现image属性并将自己绘制为一个正方形,里面有一个图像。

现在我想让块可移动,但我也想保留不可移动的块。基本上我必须创建MovableColorBlockand MovableImageBlock,它们都实现了完全相同的移动动作。类层次结构是这样的:

Block
|--ColorBlock
|----MovableColorBlock
|--ImageBlock
|----MovableImageBlock

如您所见,我执行了两次移动动作。实现这一点的另一种方法是:

Block
|--ColorBlock
|--ImageBlock
|--MovableBlock (abstract)
|----MovableColorBlock
|----MovableImageBlock

现在我只执行一次移动,但是Color两次Image。有没有简单的解决方案,还是我需要重复的代码?

4

4 回答 4

1

另一种选择是创建一个Movable接口(纯虚拟类)来声明移动方法,并派生实现这些方法的子类:


Block                 Movable
  |                     |
  +-ColorBlock----------+-MovableColorBlock
  |                     |
  +-ImageBlock----------+-MovableImageBlock

编辑

是的,如果move()子类之间的方法确实相同,那么这不是您想要的。

听起来该move()操作与该操作正交draw(),对我而言,这暗示了聚合而不是子类。所以让我们在这里稍微左转。

ABlock有一个位置;也许位置参数可能是可移动的或不可移动的:

class Position 
{
  public:

  Position( int x, int y ) : m_x(x), m_y(y) { }
  virtual ~Position() {}

  int getX() const { return m_x; }
  int getY() const { return m_y; }

  virtual bool movable() const { return false; }

  protected:

  int m_x;
  int m_y;
};

class MovablePosition : public Position
{
  public:

  MovablePosition( int x, int y ) : Position( x, y ) {}
  virtual ~MovablePosition() {}

  void move( int newX, int newY ) { m_x = newX; m_y = newY; }

  virtual bool movable() const { return true; }
};

然后您的基Block类将 aPosition作为参数:

class Block 
{
  public: 

  Block( Position *p ) : m_pos( p ) {}
  virtual ~Block() {}

  virtual void draw() = 0;

  Position *getPos() const { return m_pos; }

  protected:

  Position *m_pos;
};

然后如果你想移动一个Block子类实例,你首先要检查movable()方法:

if ( myColorBlock.getPos()->movable() )
{
  MovablePosition *p = myColorBlock.getPos();
  p->move( newX, newY );
  myColorBlock.draw();
}

无需创建冗余MovableXxxBlock类,无需重复代码。在这种方案下,块的可移动性是在运行时而不是编译时建立的;这可能与您的目标兼容,也可能不兼容。

于 2013-07-12T16:08:01.073 回答
1

你可能想看看装饰器模式

对于您的特定情况,您可以将其想象MovableBlock为 Block 的装饰器,它可以应用于ColorBlockand ImageBlock(这将是 Component 的 ConcreteComponents Block)。

这是另一个示例- 查看ScrollableWindow描述,这可能会使您更容易看到与您的示例的类比。

于 2013-07-12T14:58:20.793 回答
1

这是几乎每个图形/物理引擎都会遇到的问题。

我建议让 Movable 块成为 Block 的子类,并让 Color 和 Image 块从中派生。毕竟,一个不移动的块只是一个没有速度的移动块。

于 2013-07-12T15:00:05.253 回答
0

您可以将您MovableColorBlockMovableImageBlock朋友的类设为“MoveableBlock”,并从他们各自的“非移动”Block类继承。您仍然会有两个额外的类,但friend声明将允许它们访问移动的实现MoveableBlock

于 2013-07-12T15:00:24.257 回答