策略模式:以呼叫者为属性的策略?

时间:2018-11-14 15:40:45

标签: java design-patterns circular-dependency strategy-pattern

我使用策略模式,因此有Strategy抽象类,ConcreteStrategy类和Player类。在我的ConcreteStrategy中,我必须访问我的Player对象。

知道Player有一个Strategy,并且正如我的老师告诉我的那样,我不能在Player班级中加入Strategy,如何访问{{1 }}而不包含在Player中?

4 个答案:

答案 0 :(得分:2)

您可以将Player作为ConcreteStrategy的实例变量,例如

class PlayerStratey implements Strategy {
    Player player;
    public PlayerStrategy(Player pl) {
        player = pl;
    }
    @Override
    public void executeStrategy() {
        System.out.printf("Player %s is executing his strategy!%n", player);
    }
}

编辑:

至于“玩家有策略,而不是相反”,这对我来说几乎是一个实现细节。这是一个带有内部类的PlayerStrategy

class Player {
    Strategy strategy = new PlayerStrategy();

    // now the player "has a" strategy.
    public Strategy getStrategy() {
        return strategy();
    }

    class PlayerStrategy implements Strategy {
        @Override
        public void executeStrategy() {
            System.out.printf("Player %s is executing his strategy!%n", Player.this);
        }
    }
}

关于此设置是否有效,确实取决于Strategy的确切用途。您需要向我们提供该策略代表的实际界面。

答案 1 :(得分:0)

由于玩家执行了需要执行策略的操作,因此您可以将Player实例传递给策略方法。

interface PlayerStratey {
    void stumble(Player p);
}

class DullPlayerStratey implements PlayerStratey {
    @Override
    public void stumble(Player p) {
        p.move(ThreadLocalRandom.current().nextBoolean() ? -1 : 1);
    }
}

答案 2 :(得分:0)

您应该通过策略界面将具体策略注入您的玩家班级。然后该策略将玩家作为参数:

1-接口:

public interface Strategy {
    public void apply(Player player);
}

2-具体策略:

public class StrategyOne implements Strategy{

    public void apply(Player player) {
        System.out.println(this.getClass().getSimpleName() +" on " + player.getName());
}

   public class StrategyTwo implements Strategy {

    public void apply(Player player) {
        System.out.println(this.getClass().getSimpleName() +" on " + player.getName());
    }
}

3-上下文(此处是您的播放器类别):

public class Player {
    private Strategy strategy;
    private String name;

    public String getName(){
        return name;
    }

    public Player(Strategy strategy, String name){// construct using your chosen strategy
        this.strategy = strategy;
        this.name = name;
    }

    public void executeStrategy(Player player){
        System.out.print("Player "+ this.getName()+ " applies ");
        strategy.apply(player);
    }
}

public static void main(String[] args) {
    Player playerOne = new Player(new StrategyOne(), "playerOne");
    Player playerTwo = new Player(new StrategyTwo(), "playerTwo");
    playerOne.executeStrategy(playerOne);
    playerOne.executeStrategy(playerTwo);
    playerTwo.executeStrategy(playerTwo);
    playerTwo.executeStrategy(playerOne);
}

5-输出:

玩家playerOne在playerOne上应用StrategyOne

Player playerOne在playerTwo上应用StrategyOne

玩家playerTwo在playerTwo上应用策略Two

玩家playerTwo在playerOne上应用策略Two

然后,让您的玩家将已分配给他的策略应用到该策略所针对的玩家上。

答案 3 :(得分:0)

您可以为Player类创建一个抽象(有关更多信息,请参见 Dependency Inversion ),并将其作为参数传递给Strategy抽象类。这样,细节保持分离。

如果您确实需要避免循环依赖,则可以尝试从Player类中提取在策略中需要使用的任何内容,然后将其用作新类,然后将其作为参数传递给方法(或构造函数)在Strategy类上。