多态性与策略模式

模式和Java有什么区别?StrategyPolymorphism

我感到困惑的是,通过策略模式实现的任何东西基本上都可以通过多态性来实现。如果我在这方面错了,请纠正我。

请也为我提供例子,以消除我的困惑。


答案 1

对我来说,来自CKing帖子的链接和维基百科中的示例已经足够清楚了,但我会尝试给你一个新的示例。正如他们所说,策略模式主要是一种在运行时改变算法行为的方法。当然,您可以通过许多不同的方式实现这一目标(例如持有值和使用开关案例,但它不会像策略模式那样好)。

假设您正在开发一款回合制战略游戏,其中包含两种单位步兵坦克(单位的子类)。您的地形可以是平原铁路森林

class Unit{
    MovementStrategy ms;      
    final int baseMovement;
    int x,y;

    public Unit(int baseMovement){
        this.baseMovement = baseMovement;
    }

    abstract void fire();

    void moveForward(){
        x = x + ms.getHexagonsToMove(baseMovement);
    }

    void setMovementStrategy(MovementStrategy ms){
        this.ms = ms;
    }
}

任何单位子类都必须实现fire()方法,因为它对他们来说是完全不同的(坦克射击重型长距离子弹和步兵射击几发短距离轻型子弹)。在这个例子中,我们使用正常的多态性/继承,因为fire()方法对于任何单位来说都是不同的,并且在游戏过程中不会改变

class Infantry extends Unit{
    public Infantry(){
        super(2);
    }

    void fire(){
        //whatever
    }
}

class Tank extends Unit{
    public Tank(){
        super(5);
    }

    void fire(){
        //whatever
    }
}

单位也能够移动,并具有一个字段基础移动,该移动保存它可以行走的六边形的数量。我们正在开发一个策略游戏,而不是现实世界的模拟,所以我们不在乎它们如何移动,我们只想为它们的坐标添加一个值(在我的示例中,我只使用X坐标来获得更简单的代码)。如果所有的地形都是一样的,我们就不需要任何策略对象了......但是我们需要在运行时改变 move() 方法的行为!

因此,我们为每种地形实现不同的 MovementStrategy 类,并对游戏进行编程,以触发在每个六边形上移动的任何单位的 setMovementStrategy()。而且我们甚至不需要在 Unit 子类中编写任何其他内容。

interface MovementStrategy{
    public int getHexagonsToMove(int base);
}

class PlainMovementStrategy implements MovementStrategy{
    public int getHexagonsToMove(int base){
        return base;
    }
}

class RailroadMovementStrategy implements MovementStrategy{
    public int getHexagonsToMove(int base){
        return base*3;
    }
}

class ForestMovementStrategy implements MovementStrategy{
    public int getHexagonsToMove(int base){
        return (int)(base/2);
    }
}   

现在,当任何单位森林内移动时,我们调用

unit.setMovementStrategy(new ForestMovementStrategy());

一旦它到达平原,我们就会这样做:

unit.setMovementStrategy(new PlainMovementStrategy());

现在,我们能够根据地形更改单位的移动距离,并且不需要在任何子类中重写。

我希望这有助于您更好地了解差异。


答案 2

我感到困惑的是,通过策略模式实现的任何东西基本上都可以通过多态性来实现。

没有方向盘就不能开车。这并不意味着方向盘就是一辆汽车。同样,策略模式依赖于多态性,但这并不意味着它们是一回事。

策略模式的目的是促进组合 (has-a) 而不是继承 (is-a) 的使用。不是您的类从超类继承行为,而是在单独的类中定义行为,并且您的类具有对它的引用。

就示例而言,请看一下这个做得很好的答案。


推荐