views:

229

answers:

3

I have several Java classes which implement the strategy pattern. Each class has variable number parameters of different types:

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);
}

Now I want that the user can enter the parameters in some kind of UI. The UI should be chosen at runtime, i.e. the strategies should be independent of it. The parameter dialog should not be monolithic and there should be the possibility to make it behave and look different for each strategy and UI (e.g. console or Swing).

How would you solve this problem?

+1  A: 

One possibility to do it is with something similar to the Builder design pattern:

For every strategy type you should have a corresponding builder (one or more). The builder does not work as a normal builder receiving all init params as method arguments; Instead, it should block until the relevant input is received. Some builders will display a Swing dialog and wait, others will print to the console and wait for inputs, others can read from a file, etc. After a builder receives all inputs, it can create the strategy instance and return it.

This way you decouple the data retrieval logic from the strategy itself. Another benefit is that you can have a generic interface of all builders, so once you choose a specific builder you can manipulate it with the same piece of code.

Eyal Schneider
+1 In other words, the builders themselves would be strategies. Nice.
Péter Török
+1  A: 

The solution of this problem depends mainly on what determines which strategy is the current one. For simplicity I'm assuming that the UI is the same for all the strategies.

Practically you'll be making a builder class or a factory method. Something along this line:

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 {
    // ...
}

If you want to be real fancy you create a simple factory class to remove the act of creating into it's own class:

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);
    }

If you want to keep the UI non-monolithic, then split up the responsibilities to their own objects. Hope this helps.

Spoike
A: 

If your parameters classes contains simple object (Numbers, Boolean, Date, String) you can try to generate your interface at runtime.

It will be more difficult to generate an UI for composed objects and collection of parameters

Have a look to Metawidget it's a powerful ui generator.

Guillaume