The way how create object in Java

1. Static Factory Method

The java language offer to us the constructor for creating new object. It’s simplest way to do that but It has a lot of limitation.
So We would study the new way for creating java object. It’s the Static Factory Method.

1-1. Naming.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

class Person {
private int age;

/* It's the constructor */
public Person(int age) {
this.age = age;
}

/* Below two things are static factory method. */
public static Person young() {
return new Person(20);
}

public static Person elder() {
return new Person(70);
}
}

If you use the static factory method pattern then your source code could have the readability than the only constructor.
The example is too simple so you might not be able to understand the needs of it. but Let’s imagine your class is bigger than this.
The larger than larger things should need like static factory method pattern.

The main advantage of static factory method is It could have the name to enable express the purpose of the method.
but the constructor can’t do this. The name of some method is always important for the readability.

1-2. Instance-Controlled

The constructor always creates new instances, which need a new space for keeping itself. but static factory method wouldn’t
be as your building code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class Person {
private static Person person = new Person(0);
private int age;

public Person(int age) {
this.age = age;
}

public static Person young() {
person.age = 20;
return person;
}

public static Person old() {
person.age = 70;
return person;
}
}

It’s singleton pattern. As you can see the above, you can control the way to create the java object as the requirement.
We have called ‘Instance-Controlled’ about these attributes.

1-3. It can be returned sub-class

The constructor can be returned only itself no sub-classes.
but you could make the code more scalable if you use the static factory method like below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

class Person {
public static Person create(String type) {
if("man".equals(type)) {
return new Man();
}

if("woman".equals(type)) {
return new Woman();
}

return new Person();
}
}

class Man extends Person {}

class Woman extends Person {}

This person class can be returned all of the classes related to itself as the type parameter.
but this code has a little disadvantage, which always add the new code whenever you create new sub-class.
You could improve this code using reflection technique of java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

class Person {
public static Person create(Class<?> clazz) throws Exception {
Class[] classArgs = {};
Constructor constructor = clazz.getDeclaredConstructor(classArgs);
Object obj = constructor.newInstance();

return (Person) clazz.cast(obj);
}
}

class Man extends Person {}

class Woman extends Person {}

2. Builder

2-1. When we have a lot of optional parameters.

At this time, we would consider the situation, which have a lot of optional parameters. if we build it using the constructor,
then the number of the constructors are should be increased exponentially.

1
2
3
4
5
6
7
8
The number of fields    :   The number of constructors
1 : 1
2 : 3 (= 2 + 1)
3 : 6 (= 3 + 2 + 1)
4 : 10 (= 4 + 3 + 2 + 1)
...
10 : 45 (= 9 + 8 + ... + 2 + 1)

It looks like that we should need to use different way certainly. the first one among them is Java Beans Pattern.
It is also called getter/setter.

2-2. Java Beans Pattern

We already know this way. It would use the getter/setter methods like the below code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

class Person {
private String name;
private String sex;
private String country;
private int age;

public void setName(String name) {
this.name = name;
}

public void setSex(String sex) {
this.sex = sex;
}

public void setCountry(String country) {
this.country = country;
}

public void setAge(int age) {
this.age = age;
}
}

class Main {
public static void main(String[] args) {
Person person = new Person();

person.setName("John");
person.setAge(25);
person.setCountry("Japan");
person.setSex("M");
}
}

We could use this like the builder pattern if we return the class itself on the setter methods.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

class Person {
private String name;
private String sex;
private String country;
private int age;

public Person setName(String name) {
this.name = name;
}

public Person setSex(String sex) {
this.sex = sex;
}

public Person setCountry(String country) {
this.country = country;
}

public Person setAge(int age) {
this.age = age;
}
}

class Main {
public static void main(String[] args) {
Person person = new Person()
.setName("John")
.setAge(25)
.setCountry("Japan")
.setSex("M");
}
}

Main disadvantage of Setter methods is It couldn’t keep the consistency of the code.
It means the person object could be accessed and changed from another code after completing to create an object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Main {
public static void main(String[] args) {

/* It's the initialization of Person object */
Person person = new Person()
.setName("John")
.setAge(25)
.setCountry("Japan")
.setSex("M");

/* after this this person object can be changed. */
person.setAge(30);

}
}

2-3. Builder

It is commonly used ways all programming world when we create objects especially python or scala.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

class Person {
private String name;
private String sex;
private String country;
private int age;

static class Builder {
private final Person person;

public Builder() {
this.person = new Person();
}

public Builder name(String val) {
this.person.name = val;
return this;
}

public Builder sex(String val) {
this.person.sex = val;
return this;
}

public Builder country(String val) {
this.person.country = val;
return this;
}

public Builder age(int val) {
this.person.age = val;
return this;
}

public Person build() {
return this.person;
}
}
}

class Main {
public static void main(String[] args) {
Person person = new Person.Builder()
.name("John")
.age(25)
.country("Japan")
.sex("M")
.build();
}
}

This way should keep the consistency. That means It could not change the object attributes after creating instance.
Many things are similar with Setter pattern. It would be only main difference between them.

It’s little difficult to use builder pattern when you object has hierarchy structure.

Share