|
| 1 | +--- |
| 2 | +layout: pattern |
| 3 | +title: Parameter Object |
| 4 | +folder: parameter-object |
| 5 | +permalink: /patterns/parameter-object/ |
| 6 | +categories: Behavioral |
| 7 | +tags: |
| 8 | + - Extensibility |
| 9 | +--- |
| 10 | + |
| 11 | +## Intent |
| 12 | + |
| 13 | +The syntax of Java language doesn’t allow you to declare a method with a predefined value |
| 14 | +for a parameter. Probably the best option to achieve default method parameters in Java is |
| 15 | +by using the method overloading. Method overloading allows you to declare several methods |
| 16 | +with the same name but with a different number of parameters. But the main problem with |
| 17 | +method overloading as a solution for default parameter values reveals itself when a method |
| 18 | +accepts multiple parameters. Creating an overloaded method for each possible combination of |
| 19 | +parameters might be cumbersome. To deal with this issue, the Parameter Object pattern is used. |
| 20 | + |
| 21 | +## Explanation |
| 22 | + |
| 23 | +The Parameter Object is simply a wrapper object for all parameters of a method. |
| 24 | +It is nothing more than just a regular POJO. The advantage of the Parameter Object over a |
| 25 | +regular method parameter list is the fact that class fields can have default values. |
| 26 | +Once the wrapper class is created for the method parameter list, a corresponding builder class |
| 27 | +is also created. Usually it's an inner static class. The final step is to use the builder |
| 28 | +to construct a new parameter object. For those parameters that are skipped, |
| 29 | +their default values are going to be used. |
| 30 | + |
| 31 | + |
| 32 | +**Programmatic Example** |
| 33 | + |
| 34 | +Here's the simple `SearchService` class where Method Overloading is used to default values here. To use method overloading, either the number of arguments or argument type has to be different. |
| 35 | + |
| 36 | +```java |
| 37 | +public class SearchService { |
| 38 | + //Method Overloading example. SortOrder is defaulted in this method |
| 39 | + public String search(String type, String sortBy) { |
| 40 | + return getQuerySummary(type, sortBy, SortOrder.DESC); |
| 41 | + } |
| 42 | + |
| 43 | + /* Method Overloading example. SortBy is defaulted in this method. Note that the type has to be |
| 44 | + different here to overload the method */ |
| 45 | + public String search(String type, SortOrder sortOrder) { |
| 46 | + return getQuerySummary(type, "price", sortOrder); |
| 47 | + } |
| 48 | + |
| 49 | + private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) { |
| 50 | + return "Requesting shoes of type \"" + type + "\" sorted by \"" + sortBy + "\" in \"" |
| 51 | + + sortOrder.getValue() + "ending\" order..."; |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +``` |
| 56 | + |
| 57 | +Next we present the `SearchService` with `ParameterObject` created with Builder pattern. |
| 58 | + |
| 59 | +```java |
| 60 | +public class SearchService { |
| 61 | + |
| 62 | + /* Parameter Object example. Default values are abstracted into the Parameter Object |
| 63 | + at the time of Object creation */ |
| 64 | + public String search(ParameterObject parameterObject) { |
| 65 | + return getQuerySummary(parameterObject.getType(), parameterObject.getSortBy(), |
| 66 | + parameterObject.getSortOrder()); |
| 67 | + } |
| 68 | + |
| 69 | + private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) { |
| 70 | + return "Requesting shoes of type \"" + type + "\" sorted by \"" + sortBy + "\" in \"" |
| 71 | + + sortOrder.getValue() + "ending\" order..."; |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +public class ParameterObject { |
| 76 | + public static final String DEFAULT_SORT_BY = "price"; |
| 77 | + public static final SortOrder DEFAULT_SORT_ORDER = SortOrder.ASC; |
| 78 | + |
| 79 | + private String type; |
| 80 | + private String sortBy = DEFAULT_SORT_BY; |
| 81 | + private SortOrder sortOrder = DEFAULT_SORT_ORDER; |
| 82 | + |
| 83 | + private ParameterObject(Builder builder) { |
| 84 | + type = builder.type; |
| 85 | + sortBy = builder.sortBy != null && !builder.sortBy.isBlank() ? builder.sortBy : sortBy; |
| 86 | + sortOrder = builder.sortOrder != null ? builder.sortOrder : sortOrder; |
| 87 | + } |
| 88 | + |
| 89 | + public static Builder newBuilder() { |
| 90 | + return new Builder(); |
| 91 | + } |
| 92 | + |
| 93 | + //Getters and Setters... |
| 94 | + |
| 95 | + public static final class Builder { |
| 96 | + |
| 97 | + private String type; |
| 98 | + private String sortBy; |
| 99 | + private SortOrder sortOrder; |
| 100 | + |
| 101 | + private Builder() { |
| 102 | + } |
| 103 | + |
| 104 | + public Builder withType(String type) { |
| 105 | + this.type = type; |
| 106 | + return this; |
| 107 | + } |
| 108 | + |
| 109 | + public Builder sortBy(String sortBy) { |
| 110 | + this.sortBy = sortBy; |
| 111 | + return this; |
| 112 | + } |
| 113 | + |
| 114 | + public Builder sortOrder(SortOrder sortOrder) { |
| 115 | + this.sortOrder = sortOrder; |
| 116 | + return this; |
| 117 | + } |
| 118 | + |
| 119 | + public ParameterObject build() { |
| 120 | + return new ParameterObject(this); |
| 121 | + } |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | + |
| 126 | +``` |
| 127 | + |
| 128 | +## Class diagram |
| 129 | + |
| 130 | + |
| 131 | + |
| 132 | +## Applicability |
| 133 | + |
| 134 | +This pattern shows us the way to have default parameters for a method in Java as the language doesn't default parameters feature out of the box. |
| 135 | + |
| 136 | +## Credits |
| 137 | + |
| 138 | +- [Does Java have default parameters?](http://dolszewski.com/java/java-default-parameters) |
0 commit comments