본 내용은 Java언어로 배우는 디자인패턴 입문(한빛미디어) 책을 보면서 정리한 내용입니다.
다음과 같은 경우에 인스턴스를 복사(복제)해서 새로운 인스턴스를 만드는 패턴
Java 언어에서는 복제를 하는 조작을 'clone'이라고 부르고 있음.
자바에서는 인스턴스를 복사하는 기구로서 clone 메소드가 준비되어 있음.
clone 메소드를 실행하는 경우 복사 대상이 되는 클래스는 java.lang.Cloneable 인터페이스를 반드시 구현하고 있어야 함.
복사 대상이 되는 클래스가 직접 java.lang.Cloneable 인터페이스를 구현해도 상관없고 상위 클래스의 어딘가에서 Cloneable 인터페이스를 구현해도 상관없음.
또한 Cloneable 인터페이스의 하위 인터페이스를 구현해도 상관없음.
예제 프로그램에서는 MessageBox 클래스나 UnderlinePen 클래스는 Product 인터페이스를 구현했고, Product 인터페이스는 Cloneable 인터페이스의 하위 인터페이스로 되어 있음.
Cloneable 인터페이스를 구현한 클래스의 인스턴스는 clone 메소드를 호출하면 복사됨.
그리고 clone 메소드의 반환 값은 복사에 의해 만들어진 인스턴스가 됨.
(이때 내부에서는 복사 대상이 되는 인스턴스와 같은 크기의 메모리를 확보해서 인스턴스의 필드 내용을 복사함)
만약 Cloneable 인터페이스를 구현하지 않은 클래스의 인스턴스가 clone 메소드를 불러내면 예외 CloneNotSupportedException(clone이 지원되지 않는 예외)이 발생함.
정리하면 다음과 같음.
또한 java.lang 패키지는 암암리에 import되고 있기 때문에 소스 내에는 java.lang.Cloneable이라고 쓰지 않고 단순히 Cloneable이라고 쓸 수 있음.
clone 메소드는 java.lang.Object 클래스에서 정의되어 있음. Object 클래스는 자바의 클래스 계층에서 최상위 클래스이기 때문에 모든 클래스에서 clone 메소드를 상속하고 있음.
'Cloneable 인터페이스'라고 하면 그 안에 clone 메소드가 선언되어 있는 것처럼 생각하는 경향이 있음.
하지만 그런건 없음. Cloneable 인터페이스에는 메소드가 하나도 선언되어 있지 않음.
인터페이스는 단순히 'clone에 의해 복사할 수 있다'는 상징으로 사용되고 있음.
clone 메소드는 필드의 내용을 그대로 복사함. 바꿔 말하면 필드의 앞쪽에 있는 인스턴스의 내용까지는 고려하지 않음. clone 메소드를 사용해서 복사를 했을 경우 배열에 대한 참조만 복사될 뿐이고 배열의 요소 하나 하나는 복사되지 않음. 이와 같은 필드 대 필드의 복사를 '피상적인 복사'라고 함. clone 메소드가 수행하는 것은 바로 '피상적인 복사'임
clone이 행하는 '피상적인 복사'만으로 곤란한 경우에는 클래스 설계자가 clone 메소드를 오버라이드해서 자신에게 필요한 '복사'를 정의하는 것도 가능함. (clone 메소드를 오버라이드하는 경우에는 super.clone()을 사용해서 상위 클래스의 clone 메소드를 호출해야 함).
clone은 복사만 할 뿐이고 생성자를 호출하지는 않는다는 점이 주의.
또한 인스턴스 생성시 특수한 초기화를 필요로 하는 클래스에서는 clone 메소드 내에 처리를 기술해야 함.