Prototype Pattern 프로토타입 패턴
객체를 복사해야 하는 경우에 사용되는 디자인 패턴입니다.
예를 들어 DB 작업이 많은데, 객체를 저장해야 한다고 하면, 프로토타입 패턴을 이용해 객체를 복사(캐싱) 해놓은 뒤, DB가 여유있을 때 (?) 객체를 저장할 수 있도록 하는데 사용됩니다.
프로토타입 패턴에서 보통 객체를 복사하는 역할을 맡은 Interface는 clone 메소드 하나만 가집니다.
프로토타입 패턴의 사용
- 객체의 생성 방법이 시스템과 독립적이어야 하는 경우 ( 클래스 상속 구조와 팩토리(객체 생성 패턴) 구조가 동일한 것을 피하기 위해서)
- 객체의 인스턴스 생성/변형이 런타임에서 일어나야 하는 경우 ( 객체가 몇가지 상태 표현을 갖는 경우 매번 적절한 상태로 인스턴스를 수동으로 변화시키는 것보다 해당 상태의 프로토타입을 이용해 객체를 복제하는 것이 편리할 수 있습니다.)
프로토타입 패턴의 장단점
장점
- 미리 만들어진 프로토타입을 이용하여 반복적인 객체 초기화 작업을 줄일 수 있습니다.
- 복잡한 구조나 변수를 가진 객체를 좀더 편리하게 생성할 수 있습니다.
- 서브 클래스를 줄일 수 있습니다.
단점
- 실제 객체 클래스는 고객에게는 감춰지게 됩니다. (고객은 프로토타입을 통해서 객체에 접근합니다.)
- 서브클래스마다 clone 메소드를 구현해야 할 수 있습니다.
프로토타입 패턴 구현
복사 메소드를 사용하기 위해 Cloneable를 implements 했습니다. cloneable은 얇은 복사를 가능하게 해주는 기능힙니다.
* 얕은 복사 : 기본타입이면 실제 값이 , 참조타입이면 객체의 번지(주소값)이 복사됨.
* https://mantaray.tistory.com/26#clone()
abstract class Shape implements Cloneable {
private String name;
public Shape(String name) {
this.name = name;
}
public Shape(Shape shape) {
super();
this.name = shape.name;
}
public String getName() {
return name;
}
@Override
public Object clone() {
try {
return (Shape) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
public class Circle extends Shape {
public Circle() {
super("Circle");
}
public Circle(Circle shape) {
super(shape);
}
}
public class Triangle extends Shape{
public Triangle() {
super("Triangle");
}
public Triangle(Triangle shape) {
super(shape);
}
}
public class Prototype {
private static Map<Integer, Shape> shapeMap = new HashMap<>();
public static Shape getShape(Integer id) {
return (Shape) shapeMap.get(id).clone();
}
public static void setShape(Integer id, Shape shape) {
shapeMap.put(id, shape);
}
}
public class Main {
public static void main(String[] args) {
prototype prototype = new prototype();
Shape orgin1 = new Triangle();
Shape orgin2 = new Circle();
Shape orgin3 = new Triangle();
prototype.setShape(1, orgin1);
prototype.setShape(2, orgin2);
prototype.setShape(3, orgin3);
Shape clone1 = prototype.getShape(1);
System.out.println( "orgin1 : hashCode="+orgin1.toString()
+ ", name="+ orgin1.getName()
+ ", name hashCode="+orgin1.getName().hashCode());
System.out.println( "clone1 : hashCode="+clone1.toString()
+ ", name="+ clone1.getName()
+ ", name hashCode="+clone1.getName().hashCode());
Shape clone2 = prototype.getShape(2);
System.out.println( "orgin2 : hashCode=" +orgin2.toString()
+ ", name="+ orgin2.getName()
+ ", name hashCode="+orgin2.getName().hashCode());
System.out.println("clone2 : hashCode=" +clone2.toString()
+ ", name="+ clone2.getName()
+ ", name hashCode="+clone2.getName().hashCode());
Shape clone3 = prototype.getShape(3);
System.out.println( "orgin3 : hashCode=" +orgin3.toString()
+ ", name="+ orgin3.getName()
+ ", name hashCode="+orgin3.getName().hashCode());
System.out.println("clone3 : hashCode=" +clone3.toString()
+ ", name="+ clone3.getName()
+ ", name hashCode="+clone3.getName().hashCode());
}
}
객체의 주소값은 다르지만 데이터의 주소값은 같은 객체가 복사됬음을 확인할 수 있습니다.
orgin1 : hashCode=javatest.designPattern.prototype.Triangle@71be98f5, name=Triangle, name hashCode=1562406440
clone1 : hashCode=javatest.designPattern.prototype.Triangle@6fadae5d, name=Triangle, name hashCode=1562406440
orgin2 : hashCode=javatest.designPattern.prototype.Circle@17f6480, name=Circle, name hashCode=2018617584
clone2 : hashCode=javatest.designPattern.prototype.Circle@2d6e8792, name=Circle, name hashCode=2018617584
orgin3 : hashCode=javatest.designPattern.prototype.Triangle@2812cbfa, name=Triangle, name hashCode=1562406440
clone3 : hashCode=javatest.designPattern.prototype.Triangle@2acf57e3, name=Triangle, name hashCode=1562406440
참조
'JAVA > DesignPattern' 카테고리의 다른 글
Design Pattern 디자인 패턴 Bridge Pattern 브릿지 패턴 (0) | 2021.12.16 |
---|---|
Design Pattern 디자인패턴 Adapter Pattern 어답터 패턴 (0) | 2021.12.16 |
Design Pattern 디자인 패턴 Builder Pattern 빌더 패턴 (0) | 2021.12.15 |
Design Pattern 디자인패턴 Singleton Pattern 싱글톤 패턴 (0) | 2021.12.14 |
Design Pattern 디자인 패턴 Abstract Factory Pattern 추상 팩토리 패턴 (0) | 2021.12.13 |