I want to represent an web service URL request as an object, and found that there are lots of common parameters that could be “bubbled up” in an inheritance hierarchy. A request could have lots of parameters, some mandatory and other optional, for which I believe Bloch’s Builder pattern is a nice option, emulating named arguments with a fluent interface.
Specifically, I’m designing for the Google Maps web service API, that has as general web service request
http://maps.googleapis.com/maps/api/service/output?{parameters}
service and output are mandatory arguments, and sensor a mandatory parameter. There is also an optional parameter language.
Each service has its set of mandatory and optional parameters.The Geocode service has two optional parameters, bounds and region. It also has mutually exclusive mandatory parameters, address or location, that specify the type of service (direct or reverse geocoding, respectively). I represent this mutual exclusion with new children classes.
I imagine the class hierarchy as such:
.-----.
| Url |
'-----'
^
|
.---------.
| Request |
'---------'
^
|----------------------------+--------------...
.---------. .------------.
| Geocode | | Directions |
'---------' '------------'
^ ^
|------------+ .
.--------. .---------. .
| Direct | | Reverse | .
'--------' '---------'
Then, I would like to do something like the following:
String output = "xml";
boolean sensor = true;
String address = "Av. Paulista, São Paulo, Brasil";
Bounds bounds = new Bounds(-20, -10, -25, -20); //Geographic rectangle
String region = "br";
String lang = "pt-BR";
Coord location = new Coord(-12,-22);
DirectGeocodeRequestUrl direct =
new DirectGeocodeRequestUrl.Builder(output, sensor, address)
.bounds(bounds)
.language(lang)
.build();
ReverseGeocodeRequestUrl reverse =
new ReverseGeocodeRequestUrl.Builder(output, sensor, location)
.language(lang)
.region(region)
.build();
How can I create a Builder that uses arguments and methods from the class and superclasses in which it is inserted?
I’m building my answer upon https://stackoverflow.com/a/9138629/946814, but considering this multi-level hierarchy.
What we need is to replicate the same hierarchy with the Builder inner classes. As we want method chaining, we need a
getThis()method that returns the leaf object of the hierarchy. In order to pass its type upward the hierarchy, the parent classes have a genericT, and the leaf bindsTto itself.It assures type-safety and avoids any exception throwing due to uninitialized mandatory parameters or typos, plus the nice fluent interface. However, it’s a very costy and complex design to represent such a simple structure as an URL. I hope it is useful to someone – I preferred string concatenation at the end.
RequestUrl:
GeocodeRequestUrl:
DirectGeocodeRequestUrl:
ReverseGeocodeRequestUrl: