1. Overview
In this tutorial, we'll look at the use cases of Telescoping Constructor and how to implement it.
2. When To Use
Suppose that we have a class with multiple properties and it can be initialized in various ways. It means that we have several property combinations to define a constructor.
Or suppose that we have a class with multiple properties where some properties are mandatory and others are optional. Thus, we must have multiple constructors and most of these constructors will be created just for convenience. Otherwise, we'll be forcing the client to supply all property values, even if the client doesn't know what it must provide in the first place.
In the end, we'll have multiple constructors containing similar logic, thus duplicating code. Also when we need to change the processing of a property, we must apply this change on all related constructors. The constructors will be hard to update and maintain with the risk of breaking clients.
The Telescoping Constructor pattern aims to mitigate most of these problems.
3. How To Implement
First of all, we may not consider the Telescoping Constructor as a full-fledged design pattern, but it is definitely a good programming practice.
We'll work with the Person entity which has multiple properties.
As the first step, let's start with a dirty implementation which creates several constructors for several property combinations:
public class DirtyPerson {
private final String name;
private final String lastName;
private final int age;
private final String profession;
private final List<String> hobbies;
public DirtyPerson(String name, String lastName) {
this.name = name;
this.lastName = lastName;
this.age = 0;
this.profession = null;
this.hobbies = new ArrayList<>();
}
public DirtyPerson(String name, String lastName, int age) {
this.name = name;
this.lastName = lastName;
this.age = age;
this.profession = null;
this.hobbies = new ArrayList<>();
}
public DirtyPerson(String name, String lastName, int age, String profession) {
this.name = name;
this.lastName = lastName;
this.age = age;
this.profession = profession;
this.hobbies = new ArrayList<>();
}
public DirtyPerson(String name, String lastName, int age, String profession, List<String> hobbies) {
this.name = name;
this.lastName = lastName;
this.age = age;
this.profession = profession;
this.hobbies = hobbies == null ? new ArrayList<>() : new ArrayList<>(hobbies);
}
public String getName() {
return name;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getProfession() {
return profession;
}
public List<String> getHobbies() {
return Collections.unmodifiableList(hobbies);
}
}
Here, there are four constructors and each has similar statements thus duplicating code.
Now, let's look at whether we can provide a better implementation with Telescoping Constructor.
Firstly, we can delegate a common operation to another constructor that already implemented it. Delegation starts from one constructor to another more specific one. For example, the constructor with two parameters calls the constructor that has three parameters. Additionally, while we're doing this delegation, we also provide a default value for the unsupplied parameter values.
public class Person {
private final String name;
private final String lastName;
private final int age;
private final String profession;
private final List<String> hobbies;
public Person(String name, String lastName) {
this(name, lastName, 0);
}
public Person(String name, String lastName, int age) {
this(name, lastName, age, null);
}
public Person(String name, String lastName, int age, String profession) {
this(name, lastName, age, profession, null);
}
public Person(String name, String lastName, int age, String profession, List<String> hobbies) {
this.name = name;
this.lastName = lastName;
this.age = age;
this.profession = profession;
this.hobbies = hobbies == null ? new ArrayList<>() : new ArrayList<>(hobbies);
}
public String getName() {
return name;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getProfession() {
return profession;
}
public List<String> getHobbies() {
return Collections.unmodifiableList(hobbies);
}
}
As we can see, code duplication isn't a problem anymore.
Let's also look at the sample invocations:
public class ClientMain {
public static void main(String[] args) {
Person person = new Person("name", "lastName");
System.out.println(person);
person = new Person("name", "lastName", 20);
System.out.println(person);
person = new Person("name", "lastName", 20, "Engineer");
System.out.println(person);
person = new Person("name", "lastName", 20, "Engineer", Arrays.asList("Fishing"));
System.out.println(person);
}
}
4. Summary
In this tutorial, we've investigated the Telescoping Constructor pattern and removed the code duplication for classes which has several constructor combinations.
As always, the source code for all examples in this tutorial is available on Github