gpt4 book ai didi

Java 策略模式——我可以在 Context 类中委托(delegate)策略实例化吗?

转载 作者:搜寻专家 更新时间:2023-11-01 02:43:49 26 4
gpt4 key购买 nike

我目前正在自学设计模式。当我研究策略模式时,我发现了一些对我来说看起来很奇怪的东西。我寻找有关此模式的讨论,但没有人回答我的问题……我如何实现策略模式以使其干净、保持封装并使添加新策略变得容易。在这里解释我的问题是“规范”策略模式:

public interface Strategy {
public void run();
}

public class stratConcrt1 implements Strategy {/*run() implementation*/}
public class stratConcrt2 implements Strategy {/*run() implementation*/}

public class Context {
private Strategy strategy;

public Context(Strategy strat) {
this.strategy = strat;
}

public void runStrategy() {
this.strategy.run()
}
}


public class Client {
public void main(Strings[] args) {
Context cx;

cx = new Context(new stratConcrt1())
cx.runStrategy();

cx = new Context(new stratConcrt2())
cx.runStrategy();
}
}

我明白这是怎么回事,但让客户知道一些可以应用的不同策略我觉得很奇怪。对我来说,让 Context 实例化不同的策略而不是 Client 会更清晰,因为 Context 处理策略它应该(至少在我看来)是唯一能够实例化策略的策略。

我使用 JavaFx 实现了一个小示例,但与上面的代码有一些不同:

我有一个实例化坐标列表的类 Field,这个类有一个对列表进行排序的方法。对坐标列表进行排序的方法是有多种策略的方法。

public class Field {

// a field contains rectangles described in a list through their coordinates
private ObservableList<Coordinate> mpv_coordinateList = FXCollections
.observableArrayList();

private Context mpv_sortContext;

// Constructor
public Field() {
//the rectangles are randomly created
Random rd = new Random();
for (int i = 0; i < 100; i++) {
mpv_coordinateList.add(new Coordinate(rd.nextInt(490), rd.nextInt(490)));
}

//a context to dynamically modify the sort algorithm
mpv_sortContext = new Context();
}

//returns the list with all rectangle
public ObservableList<Coordinate> getField() {
return this.mpv_coordinateList;
}

//sort elements (depending on different algorithms)
public ObservableList<Coordinate> sortElements(String p_sortToApply) {
return mpv_sortContext.launchSort(p_sortToApply,
this.mpv_coordinateList);
}
}

正如模型所说,我创建了一个接口(interface),并让从这个接口(interface)继承的具体策略:

public interface SortStrategy {
ObservableList<Coordinate> sort(ObservableList<Coordinate> p_listToSort);
}

public class EvenSort implements SortStrategy {
@Override
public ObservableList<Coordinate> sort(
ObservableList<Coordinate> p_listToSort) {

ObservableList<Coordinate> oddCoordList = FXCollections
.observableArrayList();

for (Coordinate coord : p_listToSort) {
if (coord.x % 2 == 0) {
oddCoordList.add(coord);
}
}
return oddCoordList;
}
}

public class OddSort implements SortStrategy {
@Override
public ObservableList<Coordinate> sort(
ObservableList<Coordinate> p_listToSort) {

ObservableList<Coordinate> oddCoordList = FXCollections
.observableArrayList();

for (Coordinate coord : p_listToSort) {
if (coord.x % 2 == 1) {
oddCoordList.add(coord);
}
}
return oddCoordList;
}
}

具体类只返回一个列表,其中包含所有具有偶数或奇数 x 坐标的坐标。

然后我创建了一个类上下文:

public class Context {
//private SortStrategy mpv_sortStrategy; //never used

private EvenSort mpv_evenSort = new EvenSort();
private OddSort mpv_oddSort = new OddSort();
private StandardSort mpv_standardSort = new StandardSort();

private HashMap<String, SortStrategy> mpv_HashMapStrategies;


public Context() {

//creation of a dictionary with all possible strategies
mpv_HashMapStrategies = new HashMap<String, SortStrategy>();
mpv_HashMapStrategies.put("Even Sort", mpv_evenSort);
mpv_HashMapStrategies.put("Odd Sort", mpv_oddSort);
mpv_HashMapStrategies.put("Standard Sort", mpv_standardSort);
}

public ObservableList<Coordinate> launchSort(String p_sortToApply, ObservableList<Coordinate> p_listToSort){
return mpv_HashMapStrategies.get(p_sortToApply).sort(p_listToSort);
}
}

通过图形用户界面,用户可以选择他想用来对列表进行排序的策略。用户可以单击按钮来启动排序。通过主类(未显示)完成对 inst_field.mpv_sortContext.sortElements(a_string) 的调用,并将字符串作为描述要使用的策略的参数。然后在 sortElements 中使用该字符串来选择用户想要应用的策略实例。

在我的实现中,一方面是客户端,另一方面是处理策略(上下文、接口(interface)和具体类)的所有代码。如果我想添加一个新策略,我只需要在 Context 类中添加一个新策略的实例,并在 gui 中添加一个新策略的描述,让用户知道它。

我知道在我完成的实现中也不是很好,因为 Context 包含每个可能策略的实例,因此我不需要对接口(interface)的引用,但我发现它比让 Field 更干净并且客户知道这些类。

好吧……我完全错了吗?在“规范”策略模式中我错过了什么吗? “规范”方式是实现策略模式的唯一方式吗?或者有没有更好的方法来实现这种模式,只有应该知道的类才知道策略实例,并且可以轻松添加新策略?

最佳答案

I looked for discussions on this pattern but none answered my question... which is how can I implement the Strategy pattern to let it be clean

您的“策略”不一定像您描述的那样不干净,我认为您可能对客户是谁的想法感到困惑。您的客户正在提供要使用的实现,但这可能是必要的实现细节。例如,java RMI tutorial's ComputeEngine基本上只使用这种模式。 “计算”实现由客户端传递 - 因为只有客户端知道要执行的计算。

然而,更常见的是,该策略用于提供一种方法,使逻辑在某些上下文中可配置,或者允许针对特定用途定制通用上下文。它还具有根据需要向客户端隐藏内部结构的好处。通常要这样做,要使用的策略将在内部配置到上下文中。这可能由以下人员提供:

  • 根据要处理的数据决定策略的算法
  • 根据系统状态或约束确定策略的算法
  • 允许加载实现的配置文件(Class.getResourceAsStream)。这是您的 Context 的扩展类的 map (即从众所周知的位置加载 map )。这里的一个例子是你可以提供一个“表示要使用的默认实现的策略,但允许提供新的实现作为替代策略——例如 defaultXMLParser
  • 数据本身的 Controller - 例如一个对象类型可以规定使用某种策略来计算它的值。

对于上面的前两点,您可以考虑使用工厂来推导出正确的策略。这将使实现选择问题保持本地化。

Well... Am I totally wrong? Is there something I missed in the "canonical" strategy pattern. Is the "canonical" way the one and only way to implement the Strategy pattern? or Is there a better way to implement this pattern in a way that only the classes which should know are aware of the strategy instances and in a way that adding a new strategy can be easily done?

我会说你没有错。这实际上取决于使用该策略的目的。如果这是一个内部系统问题,那么一些规则应该驱动选择(在工厂后面)。如果它出于某种原因是可配置的,那么它应该由隐藏在上下文中的配置和管理驱动(管理使用该策略的整体逻辑的类)。但是,如果它取决于用户数据或行为,那么要么数据在内部驱动选择,要么您必须接受客户必须将您的策略​​传递给您。

另请注意,此模式背后的目标是删除条件逻辑,同时保留替代实现。因此,如果您的策略导致您执行大量条件逻辑,那么您可能需要重新考虑它是否能澄清您的代码。

</warandpeace>

关于Java 策略模式——我可以在 Context 类中委托(delegate)策略实例化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27232794/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com