Frage

So I have a data class that is somewhat laid out as:

class MyData {
  String str1,str2,str3;
  Boolean bool1,bool2;
}

The attributes are to be populated based upon a String input, something like:

public void populate(String s) {
  if(s.contains("somevalue") myData.setStr1("xxx");
  if(s.constains("something else") myData.setBool1(true);
  else myData.setBool1(false);
}

This is, of course, a pretty horrible way to do things as s.contains are actually some pretty hairy conditions, so instead I defined an interface:

public interface DataFinderInterface {
    public String findStringData(final String input);
    public Boolean findBooleanData(final String input);
}

Therefore the populate method could be rewritten as:

public void populate(String s) {
  myData.setStr1(str1Finder.findStringData(s));
  myData.setBool1(bool1Finder.findBooleanData(s);
}

The implementations of this interface either define a findStringData or a findBooleanData, which is quite unsatisfying. The populate method needs to know if we are expecting to use the findStringData method or the findBooleanData method.

Is there a better way to do this? Am I being overly picky, because the populate method needs to know what instance of DataFinderInterface to assign to what field anyway?

War es hilfreich?

Lösung

A single findData method returning a String should be sufficient: the code that processes Booleans can put a call to Boolean.getBoolean() on top of it:

public interface DataFinderInterface {
    public String findData(final String input);
}
...
myData.setBool1(Boolean.getBoolean(bool1Finder.findData(s));

Andere Tipps

The problem with the above (or ONE of the problems) is that you are always calling setStr1 AND setBool1 and I assume you will be calling all of the others as well.

If you MUST use something like the above pattern you might want to consider having MyData hold AtomicRefernce<String> and AtomicReference<Boolean>. Then have getSettableString and getSettableBoolean methods that returns the appropriate reference or null if no match.

If it is only the interface method signature you are worried about this could be solved using generics. However it does seem a little weird to initialize an object from a string that way. Perhaps if you add more details about what problem you are trying to solve, there might be a better solution.

public interface DataFinder<T> {
    public T findData(final String input);
}

DataFinder<String> str1Finder = new ... // a class implementing DataFinder<String>
DataFinder<Boolean> bool1Finder = new ... // a class implementing DataFinder<Boolean>

public void populate(String s) {
  myData.setStr1(str1Finder.findData(s));
  myData.setBool1(bool1Finder.findData(s);
}

Consider using regular expressions to extract the data you need from the input string. I would leave the MyData class as a simple data container and build a separate class for populating it - for example, a MyDataBuilder. This class could use string matching in order to extract the fields and populate them on the object.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top