Creational_Prototype Pattern
✅
- create a new instance
- by copying an existing instance
the existing instance has a
clone() methodthe existing instance==new copied instance➡️ falsethe existing instance.equals(new copied instance) ➡️ true
✅ Diagram
👍🏻
- when creating an instance is resource expensive
- 👀 connecting to database, connecting to network
👎🏻 If we did not have prototype pattern…
- cannot clone an existing instance
1
2
3
4
5
6
GithubIssue githubIssue1 = new GithubIssue(repository);
//before prototype
//have to create new instance with constructor
GithubIssue githubIssue2 = new GithubIssue(repository);
GithubIssue githubIssue3 = githubIssue.clone(); // This will not work❌
✅ clone() from Object class
- Java by default provides the
clone()method fromObject class
✔️ Cloneable interface
- the class we want to clone must
implement Cloneable()
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
public class GithubIssue implements Cloneable{
private int id;
private String title;
private GithubRepository repository;
//then override clone()
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//and override equals()
//bc cloned instance and existing instance should be equal
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof GithubIssue that)) return false;
return id == that.id && Objects.equals(title, that.title) && Objects.equals(repository, that.repository);
}
@Override
public int hashCode() {
return Objects.hash(id, title, repository);
}
}
✔️ Main class
- ❓
existing instanceandcloned instancewill have same memory? ❌ - ❓
existing instanceandcloned instancewill have same value?equals()? ⭕️ ❓
existing instanceandcloned instancewill have same.getClass()? ⭕️- ⚠️ Default
clone()from Java is a swallow copy - so, the
Repositoryofexisting instanceandcloned instanceare the same ⭕️
1
2
3
4
5
6
7
8
GithubIssue githubIssue1 = new GithubIssue(repository);
GithubIssue githubIssue3 = (GithubIssue) githubIssue1.clone();
// githubIssue1 == githubIssue3 => false
// githubIssue1.equals(githubIssue3) => true
// githubIssue1.getClass() == githubIssue3.getClass() => true
// githubIssue1.getRepository() == githubIssue3.getRepository() => true, shallow copy
Swallow copy 🆚 Deep copy
- In
GithubIssue, it hasRepositoryas its field - in swallow copy, the
cloned instancewill have the sameRepositoryas theexisting instance - if
existing instance’sRepositorychanges, cloned instance’sRepositorywill also change- In deep copy,
cloned instancewill have its ownRepository - Even if
existing instance’sRepositorychanges, cloned instance’sRepositorywill NOT change
✅ Create my own clone() for deep copy
- If I want
cloned instanceto have a complete separateRepository - should not use
clone()from Java ❌ - Can create my own
clone()
✔️ Create my own clone()
- This way, we can have deep copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class GithubIssue implements Cloneable{
private int id;
private String title;
private GithubRepository repository;
//create new repository
//and return the newly created instance
@Override
protected Object clone() throws CloneNotSupportedException {
GithubRepository repository = new GithubRepository(); //create new repository
repository.setUser(this.repository.getUser());
repository.setName(this.repository.getName());
GithubIssue issue = new GithubIssue(repository); //new instance
issue.setId(this.id);
issue.setTitle(this.title);
return issue;
}
This post is licensed under CC BY 4.0 by the author.
