- Prototype 패턴 : 복사해서 인스턴스를 만든다
Prototype 패턴은 복사기로 문서를 복사하는 것처럼, 클래스에서 인스턴스를 생성하는 것이 아니라 인스턴스로부터 다른 인스턴스를 생성하는 패턴이다. Java의 clone 메서드와 함께 학습해보려 한다.
- 어떤 경우에 사용할까?
- 종류가 너무 많아 클래스로 정리할 수 없는 경우
- 클래스로부터 인스턴스 생성이 어려운 경우 [ ex) 마우스로 그린 도형을 나타내는 인스턴스 ]
- 프레임워크와 생성하는 인스턴스를 분리하고 싶은 경우
- 예제 코드
패키지 | 이름 | 설명 |
framework | Product | 추상 메서드 use와 createCopy가 선언되어 있는 인터페이스 |
framework | Manager | createCopy를 사용하여 인스턴스를 복제하는 클래스 |
이름 없음 | MessageBox | 문자열을 테두리로 감싸서 표시하는 클래스로 use와 createCopy를 구현 |
이름 없음 | UnderlinePen | 문자열에 밑줄을 그어 표시하는 클래스로 use와 createCopy를 구현 |
이름 없음 | Main | 동작 테스트용 클래스 |
- Product 인터페이스
public interface Product extends Cloneable {
public abstract void use(String s);
public abstract Product createCopy();
}
- Manager 클래스
import java.util.HashMap;
import java.util.Map;
public class Manager {
private Map<String, Product> showcase = new HashMap<>();
public void register(String name, Product prototype) {
showcase.put(name, prototype);
}
public Product create(String prototypeName) {
Product p = showcase.get(prototypeName);
return p.createCopy();
}
}
- MessageBox 클래스
import prototype.framework.Product;
public class MessageBox implements Product {
private char decochar;
public MessageBox(char decochar) {
this.decochar = decochar;
}
@Override
public void use(String s) {
int decolen = 1 + s.length() + 1;
for(int i = 0 ; i < decolen ; i++) {
System.out.print(decochar);
}
System.out.println();
System.out.println(decochar + s + decochar);
for(int i = 0 ; i < decolen ; i++) {
System.out.print(decochar);
}
System.out.println();
}
@Override
public Product createCopy() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
- UnderlinePen 클래스
import prototype.framework.Product;
public class UnderlinePen implements Product {
private char ulchar;
public UnderlinePen(char ulchar) {
this.ulchar = ulchar;
}
@Override
public void use(String s) {
int ulen = s.length();
System.out.println(s);
for(int i = 0 ; i < ulen ; i++) {
System.out.print(ulchar);
}
System.out.println();
}
@Override
public Product createCopy() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
- Main 클래스
import prototype.framework.Manager;
import prototype.framework.Product;
public class Main {
public static void main(String[] args) {
// 준비
Manager manager = new Manager();
UnderlinePen upen = new UnderlinePen('-');
MessageBox mbox = new MessageBox('*');
MessageBox sbox = new MessageBox('/');
// 등록
manager.register("strong message", upen);
manager.register("warning box", mbox);
manager.register("slash box", sbox);
// 생성과 사용
Product p1 = manager.create("strong message");
p1.use("Hello, world.");
Product p2 = manager.create("warning box");
p2.use("Hello, world.");
Product p3 = manager.create("slash box");
p3.use("Hello, world.");
}
}
참고문헌 : 유키 히로시 저/김성훈 역(2022), JAVA 언어로 배우는 디자인 패턴 입문, 영진닷컴
참고자료 : https://refactoring.guru/ko/design-patterns/prototype