현재 사용중인 객체의 복사본을 생성하기 위해서는 어떻게 해야할까?
생성자에 빈 객체를 생성하고 현재 객체의 정보를 복사하면 될 것이다.
이는 객체의 필드값이 private
이라면 외부에서 접근할 수 없다는 문제가 있다.
또한, 객체의 클래스타입을 정확히 알아야한 올바른 복사본을 생성할 수 있다.
객체 스스로가 자신의 내부에서 복사본을 생성해내는 방법을 사용한다면 이러한 문제들을 해결할 수 있다.
클래스 내의 메서드에서 복사본을 생성하므로 접근제한자에 상관없이 복사본을 생성할 수 있고, 클래스타입을 정확히 알아낼 필요도 없다.
이렇게 객체 스스로 자신의 복사본을 생성하는 구조를 프로토타입 패턴이라 부른다.
Java에서는
Cloneable
인터페이스를 구현해야clone()
메서드를 사용할 수 있다.
만약, 해당 인터페이스를 구현하지 않았다면CloneNotSupportedException
예외가 발생한다.또한,
Cloneable
를 구현하되 참조필드에 대한 추가적인 설정이 없다면 얕은복사가 이뤄진다는 점을 주의해야한다.
얕은복사가 이뤄진 경우, 복사본의 작업에 의해 원본객체의 정보가 손상될 위험이 있다.
이 경우에는 각 참조필드에서clone()
을 호출하는 등의 방법으로 깊은복사를 수행해야한다.
클래스 구조도를 살펴보면 기본적인 구현방식을 알아볼 수 있다.
Prototype
인터페이스는 clone()
이라는 단일 추상메서드를 보유하고있다.
이를 구현하는 클래스들은 해당 메서드를 재정의하여 자신의 정보를 매개변수로 생성자를 호출한다.
클라이언트는 현재 객체의 clone()
을 호출함으로써 동일한 정보를 가진 새로운 객체를 획득할 수 있다.
만일, 애플리케이션에서 사용하는 객체들의 정보가 민감하다면 레지스트리를 사용할 수도 있다.
레지스트리에 객체들을 저장하고, 반환시에는 복사본을 반환함으로써 원본객체의 정보를 지키는게 가능하다.
구현방식은 레지스트리에 프로토타입 배열이나 리스트를 필드로 구성하고,
객체를 반환하는 메서드에서 복사본을 반환시키면 된다.