Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way to create an object with lot of attributes

I have a domain object Invoice that has around 60 attributes, some are mandatory and some are optional. This Invoice class is a representation of a record in the underlying DB table with certain columns values wrapped with application layer classes (like Enum for a simple integer stored in the DB, Currency for a double etc.,).

This Invoice class is currently defined as follows:

  • Public full-arg constructor.
  • Public getters.
  • Protected setters.

Now, it is scaring the clients of this class who create an Invoice object, to pass all 60 odd attributes to the constructor. I am adamant against making the setters public for obvious reasons.

Could you please suggest a better way to allow creation/modification of this invoice object? Please let me know if you need more details.

like image 906
Vikdor Avatar asked Nov 30 '22 23:11

Vikdor


1 Answers

Using the Builder Pattern

Use the Builder Pattern that Joshua Bloch describes in his book Effective Java 2nd Edition. You can find the same example in http://www.javaspecialists.eu/archive/Issue163.html

Pay special attention to the line:

NutritionFacts locoCola = new NutritionFacts.Builder(240, 8) // Mandatory
                          .sodium(30) // Optional
                          .carbohydrate(28) // Optional
                          .build();


Using BeansUtils.populate

Other way is to use the method org.apache.commons.beanutils.BeanUtils.populate(Object, Map) from Apache Commons BeansUtils. In this case, you need a map to store the object's properties.

Code:

public static void main(String[] args) throws Exception {

    Map<String, Object> map = new HashMap<>();
    map.put("servingSize", 10);
    map.put("servings", 2);
    map.put("calories", 1000);
    map.put("fat", 1);

    // Create the object
    NutritionFacts bean = new NutritionFacts();

    // Populate with the map properties
    BeanUtils.populate(bean, map);

    System.out.println(ToStringBuilder.reflectionToString(bean,
            ToStringStyle.MULTI_LINE_STYLE));

}

Output:

NutritionFacts@188d2ae[
  servingSize=10
  servings=2
  calories=1000
  fat=1
  sodium=<null>
  carbohydrate=<null>
]
like image 72
Paul Vargas Avatar answered Dec 04 '22 12:12

Paul Vargas