【问题标题】:How to remove the circular dependency from this use of the Strategy pattern?如何从策略模式的这种使用中移除循环依赖?
【发布时间】:2016-07-27 14:30:29
【问题描述】:
我正在尝试理解策略模式并想出了以下示例:
- 我想创建基于国际象棋的新游戏,但棋子的移动方式不同。
- 我还想使用策略模式将行为(它们如何移动)注入到各个部分中。
但如果我们有 Board、Piece 和 MoveBehavior 对象
-
Board -> Piece 因为Board 包含Pieces
-
Piece -> Board 因为一块需要传入Board 作为参数
-
MoveBehavior 需要 Board 来决定哪些动作是可以接受的。
我们怎样才能摆脱这种循环依赖?此外,这不是更现实的例子中的常见问题,因为行为需要足够大的状态来做出决定吗?我认为如果行为超级简单,不使用策略模式也没什么大不了的。
【问题讨论】:
标签:
design-patterns
strategy-pattern
【解决方案1】:
听起来您可以使用依赖注入框架来解析所有对象实例。如果您想使用不同的类型组合来实例化,您将需要一个可配置的容器。您可以将可配置容器称为策略(因为它选择了所有起作用的部分)。
我不会让开发板负责创建所有的片段和行为,而是为此使用一个作曲家类(使用依赖注入)。
这允许您(例如)为板子使用行为,或者也可以创建不同的板子类型。
另请参阅this question and answer,了解依赖注入如何帮助获得松散耦合的一些背景知识。
【解决方案2】:
我只会使用Board -> Piece -> MoveBehaviour。
原因是棋盘包含棋子,棋子有自己的移动行为,具体取决于它们的类型。
MoveBehaviour 告诉作品它允许的运动,即(例如 C#,因为这是我所熟悉的)
public Move[] Moves
{
get
{
return new Move[] { Move.Horizontal, Move.Vertical };
}
}
MoveBehaviour 的工作不是查看Piece 是否可以移动到它所请求的位置。
在下面的 C# 示例中更容易解释:
public class Board
{
public List<Piece> Pieces { get; set; }
public bool CanMoveTo(Piece piece, Point location) { /*...*/ }
}
public class Piece : IMoveBehaviour
{
public Move[] Moves { get; set; }
}
public interface IMoveBehaviour
{
Move[] moves { get; set; }
}
使用Board 和Piece 中的方法,例如RequestMove、Move、IsValidMove 等...
基本上将某事的责任留给某事,而不是移动它。 MoveBehaviour 是 Piece 的行为,而不是 Boards 职责的移动验证。