6

我有几个实现策略模式的 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)都不同。

你将如何解决这个问题?

4

3 回答 3

4

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

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

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

于 2010-04-18T12:06:26.553 回答
1

这个问题的解决主要取决于是什么决定了当前的策略是什么。为简单起见,我假设所有策略的 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 非单体,则将职责拆分给自己的对象。希望这可以帮助。

于 2010-04-18T12:37:18.110 回答
0

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

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

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

于 2010-05-05T16:21:07.647 回答