I read and enjoyed the article http://blog.jooq.org/2012/01/05/the-java-fluent-api-designer-crash-course/ from Lukas Eder and I would like to create a Fluent Interface for a class.
The class has four functions ("words" fill1 to fill4) that allow to set object attributes and four function ("words" get1 to get4) that get those attributes, but only if the required attributes have been set:
First I have to fill in the basic settings (fill1). After that I am either able to get some of those settings (get1 to get3) which are Strings. Or I am able to fill in some more information (fill2 to fill4). But only after every fill2 to fill4 has been invoked at least once, the final get4 can be invoked. How do I do this?
The first graph (states are the black dots) shows what I want to do, but as you can see the ? marks the part which is not clear, because if left as it is in the first graph, it would allow get4 to be called even if only one of fill2 to fill4 has been called.
The second graph would force that each fill2 to fill4 has been called but inforces the order and restricts that if I want to change e.g. fill3, I have to reset fill2 and fill4 as well.
The last graph would do what I want, but it has 13 states! Now if I imagine I would just add one more attribute to the group of fill2 to fill4, the number of states would explode even more.
Edit: Also, after thinking about it some more, I noticed that the way I'd do this (see below), would not even be able to implement the last graph, because after fill2 is invoked, we might be in different states - depending on what happened before.
What can / should I do?
Edit: I implement my fluent interfaces a little like a facade (if I got the design pattern right). What I mean: I leave the actual class nearly untouched - returning this (as in method chaining), however having the respective state interfaces as return values in the method signatures. The states are represented by nested interfaces. Example:
public class MyClass implements MyInterface.Empty, MyInterface.Full {
String stuff;
private MyClass(){};
public static MyInterface.Empty manufactureNewInstance(){
return new MyClass();
}
public MyInterface.Full fillStuff(String stuff){
this.stuff = stuff;
return this;
}
public String getStuff(){
return stuff;
}
}
public interface MyInterface {
public interface Empty {
public MyInterface.Full fillStuff();
}
public interface Full {
public String getStuff();
}
}
public class MyMain {
pulic static void main(String[] args) {
// For explaination:
MyClass.Empty myclassEmpty = MyClass.manufactureNewInstance();
MyClass.Full myclassFull = myclassEmpty.fillStuff("Hello World 1!");
String result1 = myclassEmpty.getStuff();
// As fluent chaining:
String result2 = MyClass.manufactureNewInstance()
.fillStuff("Hello World 2!")
.getStuff();
}
}