Skip to content

Commit 1d2b61e

Browse files
committed
docs: update parameter object
1 parent bb8ca34 commit 1d2b61e

File tree

4 files changed

+127
-112
lines changed

4 files changed

+127
-112
lines changed

parameter-object/README.md

Lines changed: 118 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,171 @@
11
---
22
title: Parameter Object
3-
category: Behavioral
3+
category: Structural
44
language: en
55
tag:
6-
- Extensibility
6+
- Abstraction
7+
- Code simplification
8+
- Decoupling
9+
- Encapsulation
10+
- Object composition
711
---
812

13+
## Also known as
14+
15+
* Argument Object
16+
917
## Intent
1018

11-
The syntax of Java language doesn’t allow you to declare a method with a predefined value
12-
for a parameter. Probably the best option to achieve default method parameters in Java is
13-
by using the method overloading. Method overloading allows you to declare several methods
14-
with the same name but with a different number of parameters. But the main problem with
15-
method overloading as a solution for default parameter values reveals itself when a method
16-
accepts multiple parameters. Creating an overloaded method for each possible combination of
17-
parameters might be cumbersome. To deal with this issue, the Parameter Object pattern is used.
19+
Simplify method signatures by encapsulating parameters into a single object, promoting cleaner code and better maintainability.
1820

1921
## Explanation
2022

21-
The Parameter Object is simply a wrapper object for all parameters of a method.
22-
It is nothing more than just a regular POJO. The advantage of the Parameter Object over a
23-
regular method parameter list is the fact that class fields can have default values.
24-
Once the wrapper class is created for the method parameter list, a corresponding builder class
25-
is also created. Usually it's an inner static class. The final step is to use the builder
26-
to construct a new parameter object. For those parameters that are skipped,
27-
their default values are going to be used.
23+
Real-world example
2824

25+
> Imagine booking a travel package that includes a flight, hotel, and car rental. Instead of asking the customer to provide separate details for each component (flight details, hotel details, and car rental details) every time, a travel agent asks the customer to fill out a single comprehensive form that encapsulates all the necessary information:
26+
>
27+
> - Flight details: Departure city, destination city, departure date, return date.
28+
> - Hotel details: Hotel name, check-in date, check-out date, room type.
29+
> - Car rental details: Pickup location, drop-off location, rental dates, car type.
30+
>
31+
> In this analogy, the comprehensive form is the parameter object. It groups together all related details (parameters) into a single entity, making the booking process more streamlined and manageable. The travel agent (method) only needs to handle one form (parameter object) instead of juggling multiple pieces of information.
2932
30-
**Programmatic Example**
33+
In plain words
3134

32-
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+
> The Parameter Object pattern encapsulates multiple related parameters into a single object to simplify method signatures and enhance code maintainability.
3336
34-
```java
35-
public class SearchService {
36-
//Method Overloading example. SortOrder is defaulted in this method
37-
public String search(String type, String sortBy) {
38-
return getQuerySummary(type, sortBy, SortOrder.DESC);
39-
}
40-
41-
/* Method Overloading example. SortBy is defaulted in this method. Note that the type has to be
42-
different here to overload the method */
43-
public String search(String type, SortOrder sortOrder) {
44-
return getQuerySummary(type, "price", sortOrder);
45-
}
46-
47-
private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) {
48-
return "Requesting shoes of type \"" + type + "\" sorted by \"" + sortBy + "\" in \""
49-
+ sortOrder.getValue() + "ending\" order...";
50-
}
51-
}
37+
wiki.c2.com says
5238

53-
```
39+
> Replace the LongParameterList with a ParameterObject; an object or structure with data members representing the arguments to be passed in.
5440
55-
Next we present the `SearchService` with `ParameterObject` created with Builder pattern.
41+
**Programmatic example**
5642

57-
```java
58-
public class SearchService {
43+
The Parameter Object design pattern is a way to group multiple parameters into a single object. This simplifies method signatures and enhances code maintainability.
5944

60-
/* Parameter Object example. Default values are abstracted into the Parameter Object
61-
at the time of Object creation */
62-
public String search(ParameterObject parameterObject) {
63-
return getQuerySummary(parameterObject.getType(), parameterObject.getSortBy(),
64-
parameterObject.getSortOrder());
65-
}
66-
67-
private String getQuerySummary(String type, String sortBy, SortOrder sortOrder) {
68-
return "Requesting shoes of type \"" + type + "\" sorted by \"" + sortBy + "\" in \""
69-
+ sortOrder.getValue() + "ending\" order...";
70-
}
71-
}
45+
First, let's look at the `ParameterObject` class. This class encapsulates the parameters needed for the search operation. It uses [Builder pattern](https://java-design-patterns.com/patterns/builder/) to allow for easy creation of objects, even when there are many parameters.
7246

47+
```java
7348
public class ParameterObject {
74-
public static final String DEFAULT_SORT_BY = "price";
75-
public static final SortOrder DEFAULT_SORT_ORDER = SortOrder.ASC;
7649

77-
private String type;
78-
private String sortBy = DEFAULT_SORT_BY;
79-
private SortOrder sortOrder = DEFAULT_SORT_ORDER;
50+
private final String type;
51+
private final String sortBy;
52+
private final SortOrder sortOrder;
8053

81-
private ParameterObject(Builder builder) {
82-
type = builder.type;
83-
sortBy = builder.sortBy != null && !builder.sortBy.isBlank() ? builder.sortBy : sortBy;
84-
sortOrder = builder.sortOrder != null ? builder.sortOrder : sortOrder;
85-
}
54+
private ParameterObject(Builder builder) {
55+
this.type = builder.type;
56+
this.sortBy = builder.sortBy;
57+
this.sortOrder = builder.sortOrder;
58+
}
8659

87-
public static Builder newBuilder() {
88-
return new Builder();
89-
}
60+
public static Builder newBuilder() {
61+
return new Builder();
62+
}
9063

91-
//Getters and Setters...
64+
// getters and Builder class omitted for brevity
65+
}
66+
```
9267

93-
public static final class Builder {
68+
The `Builder` class inside `ParameterObject` provides a way to construct a `ParameterObject` instance. It has methods for setting each of the parameters, and a `build()` method to create the `ParameterObject`.
9469

95-
private String type;
96-
private String sortBy;
97-
private SortOrder sortOrder;
70+
```java
71+
public static class Builder {
9872

99-
private Builder() {
100-
}
73+
private String type = "all";
74+
private String sortBy = "price";
75+
private SortOrder sortOrder = SortOrder.ASCENDING;
10176

10277
public Builder withType(String type) {
103-
this.type = type;
104-
return this;
78+
this.type = type;
79+
return this;
10580
}
10681

10782
public Builder sortBy(String sortBy) {
108-
this.sortBy = sortBy;
109-
return this;
83+
this.sortBy = sortBy;
84+
return this;
11085
}
11186

11287
public Builder sortOrder(SortOrder sortOrder) {
113-
this.sortOrder = sortOrder;
114-
return this;
88+
this.sortOrder = sortOrder;
89+
return this;
11590
}
11691

11792
public ParameterObject build() {
118-
return new ParameterObject(this);
93+
return new ParameterObject(this);
11994
}
120-
}
12195
}
96+
```
97+
98+
The `SearchService` class has a `search()` method that takes a `ParameterObject` as a parameter. This method uses the parameters encapsulated in the `ParameterObject` to perform a search operation.
12299

100+
```java
101+
public class SearchService {
123102

103+
public String search(ParameterObject parameterObject) {
104+
return getQuerySummary(parameterObject.getType(), parameterObject.getSortBy(),
105+
parameterObject.getSortOrder());
106+
}
107+
108+
// getQuerySummary method omitted for brevity
109+
}
110+
```
111+
112+
Finally, in the `App` class, we create a `ParameterObject` using its builder, and then pass it to the `search()` method of `SearchService`.
113+
114+
```java
115+
public class App {
116+
117+
public static void main(String[] args) {
118+
ParameterObject params = ParameterObject.newBuilder()
119+
.withType("sneakers")
120+
.sortBy("brand")
121+
.build();
122+
LOGGER.info(params.toString());
123+
LOGGER.info(new SearchService().search(params));
124+
}
125+
}
124126
```
125127

128+
This example demonstrates how the Parameter Object pattern can simplify method signatures and make the code more maintainable. It also shows how the pattern can be combined with the Builder pattern to make object creation more flexible and readable.
129+
126130
## Class diagram
127131

128-
![alt text](./etc/parameter-object.png "Parameter Object")
132+
![Parameter Object](./etc/parameter-object.png "Parameter Object")
129133

130134
## Applicability
131135

132-
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.
136+
* Methods require multiple parameters that logically belong together.
137+
* There is a need to reduce the complexity of method signatures.
138+
* The parameters may need to evolve over time, adding more properties without breaking existing method signatures.
139+
* It’s beneficial to pass data through a method chain.
140+
141+
## Known Uses
142+
143+
* Java Libraries: Many Java frameworks and libraries use this pattern. For example, Java’s java.util.Calendar class has various methods where parameter objects are used to represent date and time components.
144+
* Enterprise Applications: In large enterprise systems, parameter objects are used to encapsulate configuration data passed to services or API endpoints.
145+
146+
## Consequences
147+
148+
Benefits:
149+
150+
* Encapsulation: Groups related parameters into a single object, promoting encapsulation.
151+
* Maintainability: Reduces method signature changes when parameters need to be added or modified.
152+
* Readability: Simplifies method signatures, making the code easier to read and understand.
153+
* Reusability: Parameter objects can be reused across different methods, reducing redundancy.
154+
155+
Trade-offs:
156+
157+
* Overhead: Introducing parameter objects can add some overhead, especially for simple methods that do not benefit significantly from this abstraction.
158+
* Complexity: The initial creation of parameter objects might add complexity, especially for beginners.
159+
160+
## Related Patterns
161+
162+
* [Builder](https://java-design-patterns.com/patterns/builder/): Helps in creating complex objects step-by-step, often used in conjunction with parameter objects to manage the construction of these objects.
163+
* [Composite](https://java-design-patterns.com/patterns/composite/): Sometimes used with parameter objects to handle hierarchical parameter data.
164+
* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): Can be used to create instances of parameter objects, particularly when different parameter combinations are needed.
133165

134166
## Credits
135167

136-
- [Does Java have default parameters?](http://dolszewski.com/java/java-default-parameters)
168+
* [Does Java have default parameters? - Daniel Olszewski](http://dolszewski.com/java/java-default-parameters)
169+
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
170+
* [Effective Java](https://amzn.to/4cGk2Jz)
171+
* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3TVEgaB)

parameter-object/src/main/java/com/iluwatar/parameter/object/ParameterObject.java

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@
2424
*/
2525
package com.iluwatar.parameter.object;
2626

27+
import lombok.Getter;
28+
import lombok.Setter;
29+
2730
/**
2831
* ParameterObject.
2932
*/
33+
@Getter
34+
@Setter
3035
public class ParameterObject {
3136

3237
/**
@@ -56,30 +61,6 @@ public static Builder newBuilder() {
5661
return new Builder();
5762
}
5863

59-
public String getType() {
60-
return type;
61-
}
62-
63-
public void setType(String type) {
64-
this.type = type;
65-
}
66-
67-
public String getSortBy() {
68-
return sortBy;
69-
}
70-
71-
public void setSortBy(String sortBy) {
72-
this.sortBy = sortBy;
73-
}
74-
75-
public SortOrder getSortOrder() {
76-
return sortOrder;
77-
}
78-
79-
public void setSortOrder(SortOrder sortOrder) {
80-
this.sortOrder = sortOrder;
81-
}
82-
8364
@Override
8465
public String toString() {
8566
return String.format("ParameterObject[type='%s', sortBy='%s', sortOrder='%s']",

parameter-object/src/main/java/com/iluwatar/parameter/object/SearchService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class SearchService {
3333
* Below two methods of name `search` is overloaded so that we can send a default value for
3434
* one of the criteria and call the final api. A default SortOrder is sent in the first method
3535
* and a default SortBy is sent in the second method. So two separate method definitions are
36-
* needed for having default values for one argument in each case. Hence multiple overloaded
36+
* needed for having default values for one argument in each case. Hence, multiple overloaded
3737
* methods are needed as the number of argument increases.
3838
*/
3939
public String search(String type, String sortBy) {

parameter-object/src/main/java/com/iluwatar/parameter/object/SortOrder.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,19 @@
2424
*/
2525
package com.iluwatar.parameter.object;
2626

27+
import lombok.Getter;
28+
2729
/**
2830
* enum for sort order types.
2931
*/
3032
public enum SortOrder {
3133
ASC("asc"),
3234
DESC("desc");
3335

36+
@Getter
3437
private String value;
3538

3639
SortOrder(String value) {
3740
this.value = value;
3841
}
39-
40-
public String getValue() {
41-
return value;
42-
}
4342
}

0 commit comments

Comments
 (0)