Post

프로토타입 패턴





프로토타입 패턴이란

  • 기존에 존재하던 인스턴스를 복제하여 새로운 인스턴스를 만드는 방법을 제공하는 패턴
    • 만약 어떤 인스턴스를 만드는데 디비를 탄다거나, 네트워크를 타는 등 비용이 많이 든다면
    • 그 인스턴스를 그대로 복제해서 사용함으로써 비용을 절약할 수 있을 것이다.
  • 보통 clone() 메서드를 사용하여 프로토타입 패턴을 구현한다.





간단한 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person implements Cloneable {

    private Dog dog;
    private String name;
    private int age;

    @Override
    protected Object clone() throws CloneNotSupportedException {
      return super.clone();
    }

    // constructor()
    // equals()
}

  • 사람을 나타내는 Person 클래스와
    • 사람이 키우는 강아지인 Dog 클래스가 있다.
  • Person은 Object의 clone()을 오버라이딩 하고 있다.
    • 이 메서드를 사용하기 위해선 Cloneable을 구현해야 한다.



1
2
3
4
5
6
7
8
9
Dog dog = new Dog("또롱이", 23);
Person person = new Person(dog, "김철수", 30);

Person clone = (Person) person.clone();

System.out.println(person == clone);        // false
System.out.println(person.equals(clone));   // true

  • 먼저 만들었던 person 객체와 person을 복제해 만든 clone 객체를 볼 수 있다.
    • person과 clone은 같은 인스턴스냐고 물었을 땐 false이지만,
    • 동등한 인스턴스냐고 물었을 땐 true이다.





얕은 복사

  • Object가 제공하는 clone()은 기본적으로 shallow copy이다.
    • 이는 얕은 복사란 뜻으로, 객체가 참고하고 있는 다른 인스턴스까지는 카피하지 않는 것이다.
    • 예를 들면, Person의 데이터를 전부 카피하지만 Person이 참조하는 Dog는 참조를 그대로 가져간다.



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

    private Dog dog;
    private String name;
    private int age;

    public Object clone() { // 얕은 복사
        return new Person(dog, name, age);
    }

    // constructor()
    // equals()
    // getters()
}

  • 위의 Person의 clone()은 얕은 복사로 구현한 코드이다.
  • 얕은 복사이기 때문에 dog 인스턴스를 그대로 가져간 걸 알 수 있다.



1
2
3
4
5
6
7
8
Dog dog = new Dog("또롱이", 23);
Person person = new Person(dog, "김철수", 30);

Person clone = (Person) person.clone();

System.out.println(person.getDog() == clone.getDog());        // true

  • person도 clone도 같은 인스턴스인 또롱이의 주인이 되었다.





깊은 복사

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

    private Dog dog;
    private String name;
    private int age;

    public Object clone() { // 깊은 복사
        Dog newDog = new Dog(dog.getName(), dog.getAge());

        return new Person(newDog, name, age);
    }

    // constructor()
    // equals()
    // getters()
}

  • 이번엔 clone()을 깊은 복사로 구현하였다.
  • 또롱이마저 복사하여 서로 다른 강아지 인스턴스를 참조하게 된다.



1
2
3
4
5
6
7
8
9
Dog dog = new Dog("또롱이", 23);
Person person = new Person(dog, "김철수", 30);

Person clone = (Person) person.clone();

System.out.println(person.getDog() == clone.getDog());      // false
System.out.println(person.getDog().equals(clone.getDog())); // true

  • 이번엔 아주 깊은 곳까지 복제를 해서 또롱이마저 복제했다.
  • person과 clone이 참조하는 dog 객체는 동등하나 같진 않다.





This post is licensed under CC BY 4.0 by the author.