Java 策略模式:调用方作为属性的策略?

Java 策略模式:调用方作为属性的策略?,java,design-patterns,circular-dependency,strategy-pattern,Java,Design Patterns,Circular Dependency,Strategy Pattern,我使用策略模式,因此我有我的策略抽象类、我的具体策略类和我的播放器类。在我的ConcreteStrategy中,我必须访问我的Player对象 知道Player有一个Strategy,而且正如我的老师告诉我的,我不能在Strategy课上包括Player,如何访问Player而不将其包含在Strategy中?您可以将Player作为ConcreteStrategy的实例变量,例如 class PlayerStratey implements Strategy { Player playe

我使用策略模式,因此我有我的
策略
抽象类、我的
具体策略
类和我的
播放器
类。在我的
ConcreteStrategy
中,我必须访问我的
Player
对象


知道
Player
有一个
Strategy
,而且正如我的老师告诉我的,我不能在
Strategy
课上包括
Player
,如何访问
Player
而不将其包含在
Strategy
中?

您可以将
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接口在您的player类中注入具体的策略。然后,该策略将玩家作为参数:

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-上下文(这里是您的玩家类):

5-产出:

玩家玩家向导对玩家向导应用策略一

玩家玩家向导在玩家2上应用策略1

playerTwo对playerTwo应用策略二

游戏者游戏者对游戏者应用策略二


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

您可以为
玩家
类创建一个抽象(有关更多信息,请阅读依赖项反转),并将其作为参数传递给
策略
抽象类。这样,细节保持解耦


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

Strategy
类/接口中的抽象
runStrategy(Player p)
方法怎么样?这或使用泛型类型在
策略
类中不包含单词
Player
。请添加一些类UML类图,如果没有编码,请添加一些代码片段。这会有帮助。@f1sh,请不要在评论中回答问题。在下面添加一个或多个答案。它不应该是另一种方式吗?我的意思是一个玩家有策略,而不是策略有玩家。@BraulioLopez这是我的问题。。。这样做真的合法吗?@KevinV根据你的老师,这不是:“正如我的老师告诉我的,我不能在策略课上包括玩家”@KevinV,你不会在策略课上包括玩家,所以实现了松散耦合,这就是模式的要点。如果你听老师的解释,他可能会弄错;)至于谁拥有什么(玩家/策略),这几乎是一个实现细节。我可以稍后提供一个替代方案。这并不能真正回答我的问题…从我对你的问题的理解来看,你想要使用一种策略模式,玩家在其中使用给定的策略。在这种情况下,玩家取决于所选择的策略。你的意思是你试图让策略依赖于玩家吗?简言之,我对“我如何才能访问玩家而不将其包括在我的策略中?”的回答是你不这样做。玩家访问你暗示的策略:“知道玩家有策略”@KevinV好的,我想我现在明白你的意思了=)看看更新
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());
    }
}
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);
}