参数化策略模式

Posted

技术标签:

【中文标题】参数化策略模式【英文标题】:Parametrized Strategy Pattern 【发布时间】:2011-02-09 08:40:27 【问题描述】:

我有几个实现策略模式的 Java 类。每个类都有不同类型的变数参数:

interface Strategy 
     public data execute(data);


class StrategyA implements Strategy 
     public data execute(data);


class StrategyB implements Strategy 
      public StrategyB(int paramA, int paramB);
      public data execute(data);


class StrategyC implements Strategy 
      public StrategyC(int paramA, String paramB, double paramC);
      public data execute(data);

现在我希望用户可以在某种 UI 中输入参数。 UI 应该在运行时选择,即策略应该独立于它。参数对话框不应该是单一的,应该有可能使它的行为和外观对于每个策略和 UI(例如控制台或 Swing)都不同。

你会如何解决这个问题?

【问题讨论】:

【参考方案1】:

一种可能性是使用类似于 Builder 设计模式的东西:

对于每种策略类型,您都应该有一个相应的构建器(一个或多个)。该构建器不能作为接收所有初始化参数作为方法参数的普通构建器工作;相反,它应该阻止,直到收到相关输入。一些构建器会显示一个 Swing 对话框并等待,另一些会打印到控制台并等待输入,其他构建器可以从文件中读取,等等。构建器接收到所有输入后,它可以创建策略实例并返回它。

通过这种方式,您可以将数据检索逻辑与策略本身分离。 另一个好处是您可以拥有所有构建器的通用接口,因此一旦您选择了特定的构建器,您就可以使用相同的代码对其进行操作。

【讨论】:

+1 换句话说,建设者本身就是策略。不错。【参考方案2】:

这个问题的解决主要取决于是什么决定了当前的策略。为简单起见,我假设所有策略的 UI 都是相同的。

实际上,您将创建一个构建器类或工厂方法。沿着这条线:

interface StrategyPicker 
    public Strategy getStrategy();


// Most likely used in the JFrame it is added to
class StrategyPickerUI extends JPanel implements StrategyPicker 
    // initialize the panel with all the widgets
    // and implement the getStrategy method. the getStrategy
    // method should be called after the input is done in this
    // panel (such as clicking an Ok or Apply button)


// You can also make one for the console app
class StrategyPickerSimple implements StrategyPicker 
    // ...

如果你想要真正的花哨,你可以创建一个简单的工厂类来将创建行为移除到它自己的类中:

public class StrategyFactory() 
    public static Strategy createStrategyFromParameters(StrategyParams sp) 
        // creates the Strategy object... doesn't need to be public static
        // and if it isn't, it will help making unit tests easier
    

    // This nested class could be split up to StrategyAParams, 
    // StrategyBParams, StrategyCParams
    public class StrategyParams 
        data paramA; 
        int paramB_A;
        int paramB_B;
        int paramC_A;
        String paramC_B;
        float paramC_C;
    


// in StrategyPickerUI class
    public getStrategy() 
        StrategyParams sp = new StrategyParams();
        sp.paramB_A = myJTextFieldParamB_A.getText();
           // and so on...
        return StrategyFactory.createStrategyFromParameters(sp);
    

如果您想保持 UI 非单一化,则将职责拆分给自己的对象。希望这会有所帮助。

【讨论】:

【参考方案3】:

如果您的参数类包含简单对象(数字、布尔值、日期、字符串),您可以尝试在运行时生成您的接口。

为组合对象和参数集合生成 UI 会更加困难

看看Metawidget,它是一个强大的 ui 生成器。

【讨论】:

以上是关于参数化策略模式的主要内容,如果未能解决你的问题,请参考以下文章

策略模式

vue-draggle源码中的策略模式和柯里化

研究汽车产品平台化模块化开发模式与实施策略

浅谈简单工厂模式和策略模式

Python设计模式-策略模式

如何使用静态方法作为策略设计模式的默认参数?