Skip to content

Commit 846d056

Browse files
authored
iluwatar#1638 Add Parameter Object pattern (iluwatar#1650)
* iluwatar#1638 Add Parameter Object pattern * iluwatar#1638 Fix comments and formatting for Parameter Object pattern * iluwatar#1638 Fix formatting, commenting, remove string concatenation in Parameter Object pattern * iluwatar#1638 Fix readme formatting and log parameter object
1 parent 03bc4a6 commit 846d056

File tree

12 files changed

+693
-0
lines changed

12 files changed

+693
-0
lines changed

parameter-object/README.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
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+
![alt text](./etc/parameter-object.png "Parameter Object")
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)
179 KB
Loading
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@startuml
2+
package com.iluwatar.parameter.object {
3+
class App {
4+
- LOGGER : Logger {static}
5+
+ App()
6+
+ main(args : String[]) {static}
7+
}
8+
class ParameterObject {
9+
+ DEFAULT_SORT_BY : String {static}
10+
+ DEFAULT_SORT_ORDER : SortOrder {static}
11+
- sortBy : String
12+
- sortOrder : SortOrder
13+
- type : String
14+
- ParameterObject(builder : Builder)
15+
+ getSortBy() : String
16+
+ getSortOrder() : SortOrder
17+
+ getType() : String
18+
+ newBuilder() : Builder {static}
19+
+ setSortBy(sortBy : String)
20+
+ setSortOrder(sortOrder : SortOrder)
21+
+ setType(type : String)
22+
}
23+
class Builder {
24+
- sortBy : String
25+
- sortOrder : SortOrder
26+
- type : String
27+
- Builder()
28+
+ build() : ParameterObject
29+
+ sortBy(sortBy : String) : Builder
30+
+ sortOrder(sortOrder : SortOrder) : Builder
31+
+ withType(type : String) : Builder
32+
}
33+
class SearchService {
34+
+ SearchService()
35+
- getQuerySummary(type : String, sortBy : String, sortOrder : SortOrder) : String
36+
+ search(parameterObject : ParameterObject) : String
37+
+ search(type : String, sortBy : String) : String
38+
+ search(type : String, sortOrder : SortOrder) : String
39+
}
40+
enum SortOrder {
41+
+ ASC {static}
42+
+ DESC {static}
43+
- value : String
44+
+ getValue() : String
45+
+ valueOf(name : String) : SortOrder {static}
46+
+ values() : SortOrder[] {static}
47+
}
48+
}
49+
Builder --> "-sortOrder" SortOrder
50+
Builder ..+ ParameterObject
51+
ParameterObject --> "-DEFAULT_SORT_ORDER" SortOrder
52+
@enduml

parameter-object/pom.xml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
4+
The MIT License
5+
Copyright © 2014-2019 Ilkka Seppälä
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.
24+
25+
-->
26+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
27+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
28+
<modelVersion>4.0.0</modelVersion>
29+
<parent>
30+
<groupId>com.iluwatar</groupId>
31+
<artifactId>java-design-patterns</artifactId>
32+
<version>1.24.0-SNAPSHOT</version>
33+
</parent>
34+
<artifactId>parameter-object</artifactId>
35+
<dependencies>
36+
<dependency>
37+
<groupId>org.junit.jupiter</groupId>
38+
<artifactId>junit-jupiter-engine</artifactId>
39+
<scope>test</scope>
40+
</dependency>
41+
</dependencies>
42+
<build>
43+
<plugins>
44+
<plugin>
45+
<groupId>org.apache.maven.plugins</groupId>
46+
<artifactId>maven-assembly-plugin</artifactId>
47+
<executions>
48+
<execution>
49+
<configuration>
50+
<archive>
51+
<manifest>
52+
<mainClass>com.iluwatar.parameter.object.App</mainClass>
53+
</manifest>
54+
</archive>
55+
</configuration>
56+
</execution>
57+
</executions>
58+
</plugin>
59+
</plugins>
60+
</build>
61+
</project>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* The MIT License
3+
* Copyright © 2014-2019 Ilkka Seppälä
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
package com.iluwatar.parameter.object;
25+
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
29+
/**
30+
* The syntax of Java language doesn’t allow you to declare a method with a predefined value
31+
* for a parameter. Probably the best option to achieve default method parameters in Java is
32+
* by using the method overloading. Method overloading allows you to declare several methods
33+
* with the same name but with a different number of parameters. But the main problem with
34+
* method overloading as a solution for default parameter values reveals itself when a method
35+
* accepts multiple parameters. Creating an overloaded method for each possible combination of
36+
* parameters might be cumbersome. To deal with this issue, the Parameter Object pattern is used.
37+
* The Parameter Object is simply a wrapper object for all parameters of a method.
38+
* It is nothing more than just a regular POJO. The advantage of the Parameter Object over a
39+
* regular method parameter list is the fact that class fields can have default values.
40+
* Once the wrapper class is created for the method parameter list, a corresponding builder class
41+
* is also created. Usually it's an inner static class. The final step is to use the builder
42+
* to construct a new parameter object. For those parameters that are skipped,
43+
* their default values are going to be used.
44+
*/
45+
public class App {
46+
47+
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
48+
49+
/**
50+
* Program entry point.
51+
*
52+
* @param args command line args
53+
*/
54+
public static void main(String[] args) {
55+
ParameterObject params = ParameterObject.newBuilder()
56+
.withType("sneakers")
57+
.sortBy("brand")
58+
.build();
59+
LOGGER.info(params.toString());
60+
LOGGER.info(new SearchService().search(params));
61+
}
62+
}

0 commit comments

Comments
 (0)