我已经从抽象ColorBlock
类创建了ImageBlock
和Block
类子类。
Block
实现了大小和位置,并有一个抽象方法draw()
。
ColorBlock
实现color
属性并将其自身绘制为颜色方块。
ImageBlock
实现image
属性并将其自身绘制为一个正方形,其中包含图像。
现在我想让块可以移动,但我也想保留不可移动的块。
基本上我必须创建MovableColorBlock
和MovableImageBlock
,并且它们都实现完全相同的移动动作。
类层次结构如下:
Block
|--ColorBlock
|----MovableColorBlock
|--ImageBlock
|----MovableImageBlock
如你所见,我正在实施两次移动动作。 实现这一点的另一种方法是:
Block
|--ColorBlock
|--ImageBlock
|--MovableBlock (abstract)
|----MovableColorBlock
|----MovableImageBlock
现在我只实施移动一次,但Color
和Image
两次。
有一个简单的解决方案,还是我需要重复的代码?
答案 0 :(得分:1)
您可能需要查看Decorator Pattern
对于您的特定情况,您可以将MovableBlock
想象为要阻止的装饰器,这可以应用于ColorBlock
和ImageBlock
(对于组件{{1}将是ConcreteComponents })。
以下是备用example - 请查看Block
说明,这可能会让您更容易看到与您的示例类比。
答案 1 :(得分:1)
这是一个几乎每个图形/物理引擎都会遇到的问题。
我建议让Movable块成为Block的子类,并从中获得Color和Image块。毕竟,一个不动的块只是一个没有速度的移动块。
答案 2 :(得分:1)
另一种选择是创建一个Movable
接口(纯虚拟类)来声明移动方法,并派生实现这些方法的子类:
Block Movable
| |
+-ColorBlock----------+-MovableColorBlock
| |
+-ImageBlock----------+-MovableImageBlock
修改强>
是的,如果move()
方法在子类之间真的相同,那么这不是你想要的。
听起来move()
操作与draw()
操作是对等的,这对我来说建议聚合而不是子类。所以,让我们稍稍左转。
Block
有一个位置;也许位置参数可能是可移动的:
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
类将Position
作为参数:
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
类,也不需要重复代码。在这种方案下,块的可移动性在运行时建立,而不是编译时;可能与您的目标相符也可能不兼容。
答案 3 :(得分:0)
您可以将MovableColorBlock
和MovableImageBlock
朋友类设为'MoveableBlock'并继承其各自的“非移动”Block
类。您仍然会有两个额外的类,但friend
声明将允许他们访问MoveableBlock
中的移动实现