In my application, I have to instantiate many different types of objects. Each type contains some fields and needs to be added to a containing type. How can I do this in an elegant way?
My current initialization step looks something like this:
public void testRequest() {
//All these below used classes are generated classes from xsd schema file.
CheckRequest checkRequest = new CheckRequest();
Offers offers = new Offers();
Offer offer = new Offer();
HotelOnly hotelOnly = new HotelOnly();
Hotel hotel = new Hotel();
Hotels hotels = new Hotels();
Touroperator touroperator = new Touroperator();
Provider provider = new Provider();
Rooms rooms = new Rooms();
Room room = new Room();
PersonAssignments personAssignments = new PersonAssignments();
PersonAssignment personAssignment = new PersonAssignment();
Persons persons = new Persons();
Person person = new Person();
Amounts amounts = new Amounts();
offers.getOffer().add(offer);
offer.setHotelOnly(hotelOnly);
room.setRoomCode("roomcode");
rooms.getRoom().add(room);
hotels.getHotel().add(hotel);
hotel.setRooms(rooms);
hotelOnly.setHotels(hotels);
checkRequest.setOffers(offers);
// ...and so on and so on
}
I really want to avoid writing code like this, because it's a little messy having to instantiate each object separately and then initialize each field across multiple lines of code (e.g. having to call new Offer()
and then setHotelOnly(hotelOnly)
and then add(offer)
).
What elegant methods can I use instead of what I have? Are there any "Factories
" that can be used? Do you have any references/examples to avoid writing code like this?
I'm really interested in implementing clean code.
Context:
I'm developing a RestClient
Application for sending post requests to a Webservice.
The API is represented as a xsd schema
file and I created all the Objects with JAXB
Before sending a request I have to instantiate many Objects because they have dependencies with each other. (An Offer has Hotels, a Hotel has Rooms, a Room has Persons... And these Classes are the generated ones)
Thanks for your help.
Ideally, an object should not be concerned about instantiating its dependencies. It should only worry about things that it is supposed to do with them. Have you considered any dependency injection framework? Spring or Google's Juice are quite versatile and have a small footprint.
The idea is simple, you declare the dependencies and let the framework decide when/how/where to create them and 'inject' it into your classes.
If you don't want to use any framework, you can take design notes from them and try to emulate their design patterns and tweak it for your use-case.
Also, you can simplify things to a certain extent by making proper use of Collections. For example, what additional feature does
Offers
have other than storing a collection ofOffer
? I'm not sure what your constraints there are but, if you can make that part a bit more cleaner you would have massive gains in all places where you are instantiating the objects.I've always preferred using builder-pattern-with-a-twist because it provides much more than the basic approach of the builder pattern.
Think about a builder for a URL component. How would one think about the builder methods for encapsulating access to URL attributes, are they equally important, do they interact with each other, etc? While the query parameters or fragment are optional the hostname is not; you could say that protocol is also required but for that you can have a meaningful default, like http right?
Anyway, I don't know if this makes sense to your particular problem but I thought it would be worth mentioning for others to have a look at it.
Dozer framework provides nice way to do copy values from ws object to your dto. Here is another example. Additionally if the getter/setter names are the same of both class you dont need custom converter
You can either use a constructor or a builder pattern or a variation of the builder pattern to fix the problem of having too many fields in your initialization step.
I'm going to extend your example a bit to prove my point of why these options are useful.
Understanding your example:
Lets say an
Offer
is simply a container class for 4 fields:As it stands in your example, to set values to these fields, you use setters:
Unfortunately, this means if you need an offer with values in all of the fields, you have to do what you have:
Now let's look at improving this.
Option 1: Constructors!
A constructor other than the default constructor (the default constructor is currently
Offer()
) is useful for initializing the values of the fields in your class.A version of
Offer
using constructors would look like this:Now, we can initialize it in one line!
Even better, if you never use
offer
other than that single line:offers.add(offer);
you don't even need to save it in a variable!Option 2: Builder Pattern
A builder pattern is useful if you want the option of having default values for any of your fields.
The problem a builder pattern solves is the following messy code:
See how messy that can get?
The builder pattern is another class that you put inside your class.
Now, you can not have to have so many constructors, but still are able to choose which values you want to leave default, and which you want to initialize.
That last offer is simply one with all default values. The others are default values except the ones that I set.
See how that makes things easier?
Option 3: Variation of Builder Pattern
You can also use the builder pattern by simply making your current setters return the same Offer object. It's exactly the same, except without the extra
OfferBuilder
class.Warning: As user WW states below, this option breaks JavaBeans - a standard programming convention for container classes such as Offer. So, you shouldn't use this for professional purposes, and should limit your use in your own practices.
And your new initialization code is
That last offer is simply one with all default values. The others are default values except the ones that I set.
So, while it's a lot of work, if you want to clean up your initialization step, you need to use one of these options for each of your classes that have fields in them. Then use the initialization methods that I included with each method.
Good luck! Does any of this need further explanation?
Some nice answeres are already given here!
What came to my mind as an addition is Domain Driven Design. Specific the Building blocks part, with Entity, Value Object, Aggregate, Factory etc.
A nice introduction is given in Domain Driven Design - Quickly (pdf).
I just provide this answer because it was mentioned in a comment and I think it should also be a part of this enumeration of Design Patterns.
Null Object Design Pattern
Intent
The intent of a Null Object is to encapsulate the absence of an object by providing a substitutable alternative that offers suitable default do nothing behavior. In short, a design where "nothing will come of nothing"
Use the Null Object pattern when
Here you find the full part of "Null Object" Design Pattern