[Design Pattern] 프로토 타입 (Prototype) 패턴

hsnam·2022년 2월 14일
0

디자인패턴

목록 보기
4/6
post-thumbnail

프로토 타입(Prototype Pattern)

  • 기존 인스턴스를 복제하여 새로운 인스턴스를 만드는 방법으로 복제 기능을 갖추고 있는 인스턴스를 프로토압으로 사용해 새 인스턴스를 만들 수 있는 방법이다.
  • 인스턴스를 만들때 DB에서 읽어서 인스턴스를 생성해야 하거나 HTTP를 요청하여 네트워크를 걸쳐서 인스턴스를 만들어야 할때 기존에 인스턴스를 복제하여 수정해서 효율적으로 사용 할 수 있다.

장점

  • 복잡한 객체를 만드는 과정을 숨길 수 있다.
  • 기존 객체를 복제하는 과정이 새 인스턴스를 만드는 것보다 비용(시간 또는 메모리)적인 면에서 효율적일 수 있다.
  • 추상적인 타입을 리턴할 수 있다.

단점

  • 복제한 객체를 만드는 과정 자체가 복잡할 수 있다.(특히, 순환 참조가 있는경우)

구현

  • GithubIssue Class를 새로 만들지 않고 기존 객체를 복제하여 효율적으로 객체를 만들 수 있다.
  • JAVA에서 인스턴스를 복제하기 위해서는 Object Class의 Clone()을 사용하면 된다.
  • GithubIssue은 Cloneable을 상속받아 clone()을 구현 하였다. super.clone()을 사용할 시 객체의 얕은 복사가 이루어지므로 경우에 따라 깊은 복사를 위해 객체 복사(생성) 하는 부분을 직접 구현 하였다.
package me.hsnam.prototype;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.Objects;

@Getter
@Setter
@ToString
public class GithubIssue implements Cloneable{

    private int id;

    private String title;

    private GithubRepository githubRepository;

    public String getUrl() {
        return String.format("https://github.com/%s/%s/issues/%d", githubRepository.getUser(), githubRepository.getName(), this.getId());
    }

    //얕은 복사의 Clone
//    @Override
//    public Object clone() throws CloneNotSupportedException {
//        return super.clone();
//    }

    // 깊은 복사
    @Override
    public Object clone() throws CloneNotSupportedException {
        GithubRepository repository = new GithubRepository();
        repository.setUser(this.githubRepository.getUser());
        repository.setName(this.githubRepository.getName());

        GithubIssue issue = new GithubIssue();
        issue.setTitle(this.title);
        issue.setId(this.id);
        return issue;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        GithubIssue issue = (GithubIssue) o;
        return id == issue.id && Objects.equals(title, issue.title) && Objects.equals(githubRepository, issue.githubRepository);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, title, githubRepository);
    }
}
package me.hsnam.prototype;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class GithubRepository {

    private String user;

    private String name;
}
  • Test
package prototype;

import me.hsnam.prototype.GithubIssue;
import me.hsnam.prototype.GithubRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestReporter;

import java.util.ArrayList;

public class PrototypeTest {

    @Test
    @DisplayName("prototype 패턴 테스트")
    public void prototypeTest() throws CloneNotSupportedException{
        GithubRepository githubRepository = new GithubRepository();
        githubRepository.setName("hong-brother");
        githubRepository.setUser("hsnam");

        GithubIssue issue = new GithubIssue();
        issue.setTitle("디자인 패턴 이슈");
        issue.setId(1);
        issue.setGithubRepository(githubRepository);

        // System.out.println(issue.getUrl());

        GithubIssue anotherIssue = (GithubIssue) issue.clone();

        Assertions.assertNotEquals(issue, anotherIssue);
        Assertions.assertEquals(false, issue.equals(anotherIssue));
        Assertions.assertEquals(issue.getClass(), anotherIssue.getClass());
        Assertions.assertEquals(false, issue.getGithubRepository() == anotherIssue.getGithubRepository());

    }
}

0개의 댓글