如何在子类上应用模式装饰器

Posted

技术标签:

【中文标题】如何在子类上应用模式装饰器【英文标题】:How to apply Pattern Decorator on subclass 【发布时间】:2015-03-09 07:41:19 【问题描述】:

我想将 Pattern Decorator 应用到我的 android 项目中,但在装饰器中我失去了一个对象的成员资格到他的类。例如,如果我想在我的 Level 中添加一个 Ball,我的装饰器 ColRebondBord 中的处理将应用于 AbstractGameObject 不是球。所以我不知道我的对象是球还是墙。 (一个是圆形,一个是矩形)

在 Level.java 中:

AbstractGameObject ball = new Ball (sizeball, posX, posY);
ball = new ColRebondBord(ball);//ball will rebond on the border level(screen)
lvl.add(ball);//add the ball in the Level

在 ColRebondBord.java 中:

public void collisionBorder(double xLeftTopCorner, double yLeftTopCorner, double width, double height)


    if(_GameObjectDecorated instanceof Ball) 
        //treatments for Ball Object but never comes here
    
    if(_GameObjectDecorated instanceof Wall) 
        //treatments for Wall Object but never comes here

这是在collisionBorder中截取一个断点,我以为它会在第一个IF中出现,但是没有:

有人知道我是否必须使用多态(所以在这种情况下,我必须为每个对象 Ball 和 Wall 做装饰器)或其他想法?

---编辑--- 阅读 cmets,有 2 个解决方案:(感谢 @GuillaumeS 和 @amdev)

ColRebondBord 的 2 个子类:ColRebondBordBall 和 ColRebondBordWall 做 2 个装饰器,一个用来装饰球,另一个用来装饰墙

也许可以提出其他建议

【问题讨论】:

GameObjectDecorated 的声明类型是什么?您是否尝试放置断点来检查对象的类型? @GuillaumeS 我为您添加了断点捕获。感谢您的帮助 GameObjectDecorated的类型好像是MvtSensor。 使用装饰器时不必检查子类类型。 “Ball”类的碰撞边界必须调用 super.collisionBorder()。并且你必须在两个不同的子类中实现两个不同的碰撞边框()函数,所以不要创建 ColRebondBord,而是创建子类 ColRebondBordBall 和 ColRevondBordWall。 @GuillaumeS 因为在我的真实项目中我这样做:AbstractGameObject ball = new Ball(holeSize, 0, 0);ball = new MvtSensor(ball);ball = new ColRebondBord(ball);lvl.add(ball); 【参考方案1】:

使用装饰器时不必检查子类类型。类“Ball”的碰撞边框必须调用 super.collisionBorder()。而且你必须在两个不同的类中实现两个不同的碰撞边框()函数,所以改为ColRebondBord 的子类,创建 ColRebondBordBall 和 ColRevondBordWall 的子类。

【讨论】:

【参考方案2】:

您必须仔细考虑您想要实现的目标。然后决定装饰器是否是实现这一目标的好方法。

装饰器可用于将一些常见的“装饰”应用于不同但相似的对象。例如,“BackgroundDecorator”可能会将背景颜色应用于不同的形状(cricle、矩形......)。基类必须支持装饰器可以调用的方法“setBackground”。

这里的重点:基类必须支持装饰器使用的方法,这样您就不需要进行一些 instanceof 检查。它应该适用于所有不同的子类(例如,“BorderDecorator”可能需要基类中的“getBoundingBox”方法。然后,如果它们支持“getBoundingBox”方法,他可以应用于所有类型的元素)。

装饰器也可以用于碰撞。只需在基类(可能是抽象的)中定义碰撞检测所需的方法。如果您需要更准确的检测,边界框或折线可能会有所帮助。

在考虑碰撞检测时会想到使用装饰器的其他方法。某种策略可能......“GameObject.getColisionStrategy”......

【讨论】:

您的愿景很感兴趣,谢谢。但我认为保留 amdev 的主张:做 ColRebondBord 的 2 个子类

以上是关于如何在子类上应用模式装饰器的主要内容,如果未能解决你的问题,请参考以下文章

如何装饰子类中的继承方法?

JS设计模式(12)装饰者模式

对于装饰器模式的理解

对于装饰器模式的理解

对于装饰器模式的理解

设计模式之装饰器模式