这是在Java中实现Decorator或Multiple继承的新方法吗?

时间:2015-08-31 09:05:56

标签: java architecture decorator multiple-inheritance

我想知道我是否找到了另一种在Java中实现Decorator设计模式的方法?这可能是一种在Java中执行类似于多重继承的新方法吗?是否有更好的方法来实现下面的问题?

我提供了一个最小的例子,针对以下问题(图片简单的游戏引擎):

  • Actor:是一个基本的演员,有一个位置(在屏幕上)和一个可见性标志
  • 有些演员是Damagable,这意味着他们可以通过健康点,施加伤害的方法以及摧毁它们(使基础角色隐形)进行扩展。
  • 有些演员是Physical,这意味着他们可以施加像重力一样的力量,这有效地改变了基础演员的位置。
  • 有些Actors是Damagable and Physical,所以他们应该做一种多重继承或者应用2个Decorator(使用Decorator模式)。 EnemyActor就是一个例子,当然还有自己的方法。

这是我的实现(最小化):

public class Actor {
    int posX;
    int posY;
    boolean visible = true;
}

public class DamagableActorDecoration {
    float health = 10;
    private final Actor base;

    public DamagableActorDecoration(Actor base) {
        this.base = base;
    }

    void applyDamage (float dmg) {
        health -= dmg;
        if (health<=0)
            base.visible = false;
    }

    boolean isDestroyed () {
        return health<=0;
    }
}

public class PhysicalActorDecoration {
    private final Actor base;

    public PhysicalActorDecoration(Actor base) {
        this.base = base;
    }

    public void applyGravity () {
        base.posY--;
    }
}

public interface Damagable {
    DamagableActorDecoration d();
}

public interface Physical {
    PhysicalActorDecoration p();
}

public class EnemyActor extends Actor implements Damagable, Physical{
    @Override
    public DamagableActorDecoration d() {
        return new DamagableActorDecoration(this);
    }
    @Override
    public PhysicalActorDecoration p() {
        return new PhysicalActorDecoration(this);
    }

    public void showExplodingParticleSystem (){}
}

现在我可以创建一个扩展Actor的敌人,有自己的方法,也是Damagable和Physical。例如,通过这样使用它:

public class Runner {
    public static void main(String[] args) {
        EnemyActor enemy1 = new EnemyActor();

        // basic actor behavior : appear
        enemy1.visible=true;

        // basic actor behavior : move forward
        enemy1.posX++;

        // damagable actor behavior : receive damage
        enemy1.d().applyDamage(0.7f);

        // physical actor behavior : fall down
        enemy1.p().applyGravity();

        // damagable actor behavior : be destroyed
        if (enemy1.d().isDestroyed())
        {
            // enemy actor behavior : explode into pieces
            enemy1.showExplodingParticleSystem();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

你所做的是代表团和作曲之间的事情。在我看来,&#34;可破坏&#34;和&#34;物理&#34;应该自己行动,并拥有&#34; EnemyActor&#34;委托给他们,而不是让接口委托给装饰者。我通过删除不必要的间接层来清理它。

编辑:我忘了提及。当您处理视频游戏时,有时性能优先。如果谈论的是由用户事件触发的操作,那么性能并不重要,但是如果我们谈论在循环中多次发生的操作 - 最好只是放弃和使用直接访问属性扩充Actor。

public class EnemyActor extends Actor implements Damageable, Physical {

    private final DamageableActorDecoration damageDecorator;
    private final PhysicalActorDecoration physicalDecorator;

    public EnemyActor() {
        damageDecorator = new DamageableActorDecoration(this);
        physicalDecorator = new PhysicalActorDecoration(this);
    }

    @Override
    public void applyDamage(float dmg) {
        damageDecorator.applyDamage(dmg);
    }

    @Override
    public boolean isDestroyed() {
        return damageDecorator.isDestroyed();
    }

    @Override
    public void applyGravity() {
        physicalDecorator.applyGravity();
    }
}

public class Actor {
    int posX;
    int posY;
    boolean visible = true;
}

public interface Damageable {
    void applyDamage(float dmg);

    boolean isDestroyed();
}

public class DamageableActorDecoration implements Damageable {
    float health = 10;
    private final Actor base;

    public DamageableActorDecoration(Actor base) {
        this.base = base;
    }

    @Override
    void applyDamage(float dmg) {
        health -= dmg;
        if (health <= 0)
            base.visible = false;
    }

    @Override
    boolean isDestroyed() {
        return health <= 0;
    }
}

public interface Physical {
    void applyGravity();
}

public class PhysicalActorDecoration implements Physical {
    private final Actor base;

    public PhysicalActorDecoration(Actor base) {
        this.base = base;
    }

    @Override
    public void applyGravity() {
        base.posY--;
    }
}