【问题标题】: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)都不同。

你会如何解决这个问题?

【问题讨论】:

    标签: java design-patterns oop model-view-controller strategy-pattern


    【解决方案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 生成器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多