了解装饰器设计模式

时间:2018-04-01 15:14:51

标签: java design-patterns

我在理解装饰设计模式时遇到了问题。让我们说我想在我的项目中使用它。这是一个平台游戏,所以我立即认为最好的用法是在敌人的课程。我希望有不同类型的敌人,基本的和其他的将是第一个的扩展(例如具有不同的属性,颜色,额外的AI逻辑)。根据我的理解,这是类应该是什么样子

abstract class Enemy{

    float speedX,speedY;
    int x,y,width,height;
    COLOR colour;
    Sprite sprite;

    void setAnimation();
    void update();
    void render();
    void init();

}


class EnemyBasic extends Enemy{

  EnemyBasic() {
        init();
    }

    void init() {
        //set all variables
    }
    @Override
    void setAnimation() {
        //set animation
    }

    @Override
    public void update() {
        //update
    }

    @Override
    public void render() {
        render(sprite,colour,x,y,width,height)

    }
}

class FastEnemy extends Enemy{

    Enemy basicEnemy;
    FastEnemy(Enemy basicEnemy) {
        this.basicEnemy = basicEnemy;
        init();
    }

    void init() {
        basicEnemy.init();
        maximalSpeed = basicEnemy.maximalSpeed*2;
    }
    @Override
    void setAnimation() {
        basicEnemy.setAnimation();
    }

    @Override
    public void update() {
        basicEnemy.update();
        additionalMovementLogic();
    } 

    additionalMovementLogic(){
    }

    @Override
    public void render() {
        color=green;
        basicEnemy.render()

    }
}

问题是,这不会起作用,因为来自basicEnemy对象的方法调用将对EnemyBasic字段进行操作,而不是来自EnemyFast的那些字段。例如,render()将呈现EnemyBasic对象而不是EnemyFast。只有我能看到的解决方案是重新实现整个类,但是装饰类的重点是什么呢?我理解错了吗?或者在这种情况下装饰器不应该使用?如果是这样的话应该使用

3 个答案:

答案 0 :(得分:1)

在目前的形式中,这看起来不像是Decorator Pattern的一个很好的用例,因为它需要改变basicEnemy的内部行为。我可以想到以下解决方案:

  • 创建getter和setter(即速度,颜色)
  • 将渲染提取到单独的类

这种渲染器可以获得修饰值,例如:

  1. 渲染器要求速度。
  2. Decorator在basicEnemy上调用getSpeed()并将其乘以2.
  3. 渲染器处理渲染逻辑。

答案 1 :(得分:0)

这实际上不是装饰器模式的实现 - 它只是子类化。您可以将装饰模式用于您的目的,但我建议您查看实体组件系统:

https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system

这是一种广泛用于游戏开发的设计模式,用于解决您尝试解决的各种问题。查看上面的文章和最后的外部链接。

答案 2 :(得分:0)

您可以通过 装饰器模式 进行正确的跟踪。但你必须要小心,你真正的要求是什么。

从你的代码中,我希望你会尝试这样的东西;

Enemy enemy = new EnemyFast(new EnemyBasic()); 

只有当 EnemyFast类行为= EnemyBasic类行为+一些添加时,这才有意义。

例如,在render()内部的EnemyFast方法中,类应该如下所示(与其他多态方法相同)。

注意 :类EnemyFast中的字段名称应从basicEnemy更改为enemy。从这个意义上说,这听起来更通用。

    @Override
    public void render() {
        enemy.render(); //renderlogic of basic enemy
        //implement additional logic you want, so that it would fill upto EnemyFast    
    }

因此,对于您的上一个问题,Decorator模式是一个概述对象演变的解决方案。相反,过于严格不采用纯粹的继承,Decorator模式告诉我们封装进化方法并使用组合重用它们,这为我们提供了更大的灵活性。如果我们仅通过继承(使用继承层次结构进行下调)来实现这一点,那么稍后出现的一些子类将必须继承其父类的所有方法(根本不需要)(这就是继承的原因)是一种太僵硬的方式)。所以 装饰器模式 也是使用composition over inheritance(合成/聚合)的完美示例。