티스토리 뷰
728x90
1. 프로토타입 패턴?
- 기존 인스턴스를 복제하여 새로운 인스턴스를 생성하는 방법
2. 목적
- 아래 PrototypeClient에서 GithubIssue를 새로 생성할때 처음부터 객체를 만드는것이 아니라 기존에 있는 인스턴스를 복제하여 바뀐부분만 수정하여 만들고자 함.
public class GithubIssue {
private final GithubRepository githubRepository;
private Integer id;
private String title;
public GithubIssue(GithubRepository githubRepository) {
this.githubRepository = githubRepository;
}
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
public String getUrl() { return "url"; }
}
public class GithubRepository {
private String user;
private String name;
public String getUser() { return user; }
public void setUser(String user) { this.user = user; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
public class PrototypeClient {
public static void main(String[] args) {
GithubRepository githubRepository = new GithubRepository();
githubRepository.setUser("jin-park");
githubRepository.setName("gof design pattern study");
GithubIssue githubIssue = new GithubIssue(githubRepository);
githubIssue.setId(1);
githubIssue.setTitle("1강: 싱글톤 패턴");
String url = githubIssue.getUrl();
System.out.println("url - " + url);
}
}
3. 패턴 설명
- 기존 인스턴스를 복제하기 위해서는 Object 클래스의 clone 메서드를 사용한다.
- 기존 인스턴스 != 클론 인스턴스 → cloen()은 인스턴스를 생성하므로 동일 하지 않음.
- 기존 인스턴스.equals(클론 인스턴스) → clone()은 내부 내용은 같기때문에 동등함.
3.1. clone 사용 방법
- Cloneable 인터페이스를 구현한다.
- clone() 메서드를 오버라이드 한다.
- equals와 hashCode 메서드를 오버라이드한다.
public class GithubIssue implements Cloneable {
....
....
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GithubIssue that = (GithubIssue) o;
return Objects.equals(githubRepository, that.githubRepository) && Objects
.equals(id, that.id) && Objects.equals(title, that.title);
}
@Override
public int hashCode() {
return Objects.hash(githubRepository, id, title);
}
}
public class PrototypeClient {
public static void main(String[] args) throws CloneNotSupportedException {
GithubRepository githubRepository = new GithubRepository();
githubRepository.setUser("jin.bak");
githubRepository.setName("gof design pattern study");
GithubIssue githubIssue = new GithubIssue(githubRepository);
githubIssue.setId(1);
githubIssue.setTitle("1강: 싱글톤 패턴");
GithubIssue clone = (GithubIssue) githubIssue.clone();
System.out.println("githubIssue == clone -> " + (githubIssue != clone)); // true
System.out.println("githubIssue.equals(clone) -> " + githubIssue.equals(clone)); // true
System.out.println("githubIssue.getClass() == clone.getClass() -> " + (githubIssue.getClass() == clone.getClass())); // true
}
}
3.2. clone 메서드 특징 - 얕은 복사
3.2.1. 깊은 복사 vs 얕은 복사
- 얕은 복사 - 객체를 복사시에 주소(레퍼런스)만 복사해 오는 방식, 한 쪽에서 수정이 발생되면 다른쪽에도 영향을 끼쳐 같아짐.
- 깊은 복사 - 주소값을 참조하는 것이 아닌, 새로운 메모리 공간에 값을 복사하는 방식.
3.2.2. 얕은 복사로 인한 문제점
- 위에 githubIssue.clone()를 실행하면 내부에 참조하고 있는 githubRepository는 얕은 복사로 같은 인스턴스를 가지고있게된다.
- 만약 githubRepository를 수정하게 되면 githubIssue와 clone된 인스턴스 내부의 githubRepository내용이 모두 바뀐다.
public class PrototypeClient {
public static void main(String[] args) throws CloneNotSupportedException {
....
System.out.println(clone.getGithubRepository() == githubIssue.getGithubRepository()); // true
}
}
3.3. clone 메서드 - 깊은 복사로 변경
ublic class GithubIssue implements Cloneable {
....
....
@Override
protected Object clone() throws CloneNotSupportedException {
GithubRepository githubRepository = new GithubRepository();
githubRepository.setUser(this.githubRepository.getUser());
githubRepository.setName(this.githubRepository.getName());
GithubIssue githubIssue = new GithubIssue(githubRepository);
githubIssue.setId(this.id);
githubIssue.setTitle(this.title);
return githubIssue;
}
....
....
}
4. 장점 및 단점
4.1. 장점
- 복잡한 객체를 만드는 과정을 숨길수 있다.
- 새 객체를 생성하는 것 보다 비용(시간, 메모리)적인 면에서 효율적일 수도 있다.
- 추상적인 타입을 리턴할 수 있다.
4.2. 단점
- 객체 생성이 복잡한 경우 clone 메서드 구현 또한 복잡해질 수 있다. (특히 순환참조의 경우)
위글은 인프런의 코딩으로 학습하는 GoF의 디자인 패턴강의를 정리하였습니다.
백기선님의 수락으로 정리하였으며 더 자세한 내용은 강의를 수강하시기 바랍니다.
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard
728x90
'디자인 패턴' 카테고리의 다른 글
07. 브릿지 패턴 (0) | 2022.02.10 |
---|---|
06. 어댑터 패턴 (0) | 2022.02.10 |
04. 빌더패턴 (0) | 2022.02.10 |
03. 추상 팩토리 패턴 (0) | 2022.02.10 |
02. 팩토리 메소드 패턴 (0) | 2022.02.10 |
댓글