프로토타입 패턴 (Prototype Pattern)

niireymik·2024년 8월 26일



🖨️ Prototype Pattern

프로토타입 패턴은 GoF 디자인 패턴의 생성 패턴 중 하나로, 기존의 인스턴스를 복제해 새로운 인스턴스를 만드는 방법이다!

프로토타입 패턴은 클래스에 의존하지 않으면서도, 기존 객체를 복제하게 해준다. 복제 시에는 실제로 복제되는 객체제 복제 프로세스를 위임하며, 여기서 복제를 지원하는 객체를 프로토타입이라고 부르는 것이다! :>

프로토 타입 사용 이유

프로토타입 패턴이 왜 필요할까? 객체 복사는 쉽지 않나? 라는 의문이 따른다. 그러나, 객체 복사는 쉽지 않다!
객체 복사를 위해서는 클래스로부터 인스턴스를 만들어낸 뒤 모든 값을 설정해줘야 하는데, 이는 다음과 같은 문제가 생길 수 있다.

  • 비공개 필드가 있는 경우 해당 필드의 값 설정이 어렵다.
  • 클라이언트 입장에서는 인터페이스만 알고, 구현체에 대해 모를 수 있어서 복사하기 까다로울 수 있다.
  • 많은 상속을 통해 다양한 필드를 늘려온 객체의 경우 필드 값을 복제하는 일이 생각보다 쉽지 않다.
  • 프로토타입 레지스트리를 사용하면, 설정이 복잡하지만 자주 사용되는 객체를 저장해두고 계속 복사해서 사용하는 것이 가능하다.

구조도 Class Diagram

인터페이스 Prototypeclone() 메서드를 가진다. ConcretePrototypeAConcretePrototypeB 클래스는 각각 Prototype 인터페이스를 받아서 clone() 메서드를 구현한다. 클라이언트는 Prototypeclone() 메서드를 사용해 객체를 복제한다.

다시 말해, 프로토타입 인터페이스는 clone()이라는 공통의 메서드를 제공하는 역할이고, ConcretePrototypeA, ConcretePrototypeB는 서로 다른 클래스로서 존재하되, 동일한 인터페이스의 clone() 메서드를 각 클래스에 맞게 구현한다. 이로써 사용자는 A의 객체를 복제하고 싶다면 A.clone(), B의 객체를 복제하고 싶다면 B.clone()과 같이 프로토타입의 동일한 메서드를 사용해 객체를 복제할 수 있다. 실제 동작은 다르지만 클라이언트는 동일한 것으로 인지하고 사용할 수 있는 것이다!




🫧 프로토타입 패턴 구현

구조도에서 Prototype 인터페이스가 있었다. 자바에서는 프로토타입의 역할을 하는 Cloneable 인터페이스를 제공한다.

(+) 여러 프로토타입 패턴 구현 사례를 찾아본 결과, A라는 하나의 클래스 또는 인터페이스가 Cloneable을 상속받고, 다른 클래스들이 A를 받아서 구현하거나 하는 등의 다양한 사례가 많아서 헷갈렸다. 프로토타입 패턴의 정석적인 클래스 다이어그램과 코드의 형태가 어긋난 사례가 많았다.
→ 더 깊게 찾아본 결과, Java를 기준으로, 프로토타입 패턴처럼 동일한 복제 메서드의 제공을 위해 Java에서 제공하는 것이 Cloneable 인터페이스이며, 이것이 구조도의 Prototype에 해당하는 것이라고 결론지을 수 있었다.

Circle, Dot, Line 클래스는 Cloneable 인터페이스를 받아 clone() 메서드를 오버라이딩한다.

public class Circle implements Cloneable {

    Integer x;
    Integer y;
    Integer r;

    public Circle(Integer x, Integer y, Integer r) {
        this.x = x;
        this.y = y;
        this.r = r;
    }

    public void view() {
        System.out.println("Cicle ( " + x + ", " + y + " )" + " r : " + r);
    }

    @Override
    public Circle clone() throws CloneNotSupportedException {
        return new Circle(this.x, this.y, this.r);
    }
}
public class Dot implements Cloneable{

    Integer x;
    Integer y;
    Boolean isEmpty;

    public Dot(Integer x, Integer y, Boolean isEmpty) {
        this.x = x;
        this.y = y;
        this.isEmpty = isEmpty;
    }

    public void view() {
        System.out.println("Dot ( " + x + ", " + y + " )" + " isEmpty : " + isEmpty);
    }

    @Override
    public Dot clone() throws CloneNotSupportedException {
        return new Dot(this.x, this.y, this.isEmpty);
    }

}
public class Line implements Cloneable {

    Integer x;
    Integer y;
    Float angle;

    public Line(Integer x, Integer y, Float angle) {
        this.x = x;
        this.y = y;
        this.angle = angle;
    }

    public void view() {
        System.out.println("Line ( " + x + ", " + y + " )" + " angle : " + angle);
    }

    @Override
    public Line clone() throws CloneNotSupportedException {
        return new Line(this.x, this.y, this.angle);
    }

}

Main에서는 세부적인 구현 내용을 알 필요 없이, 각 객체에 clone() 메서드를 동일하게 사용해 객체를 복제할 수 있다!

public class Main {

    public static void main(String[] args) throws CloneNotSupportedException {

        Circle circle = new Circle(1, 1, 3);
        Dot dot = new Dot(-1, 0, false);
        Line line = new Line(0, 0, 0.5f);

        Circle circle1 = circle.clone();
        Dot dot1 = dot.clone();
        Line line1 = line.clone();

        circle.view();
        circle1.view();
        dot.view();
        dot1.view();
        line.view();
        line1.view();

    }
}

📌 출력 결과

Cicle ( 1, 1 ) r : 3
Cicle ( 1, 1 ) r : 3
Dot ( -1, 0 ) isEmpty : false
Dot ( -1, 0 ) isEmpty : false
Line ( 0, 0 ) angle : 0.5
Line ( 0, 0 ) angle : 0.5

→ 동일한 clone() 메서드를 사용해 각 객체가 잘 복사되었음을 확인할 수 있다 :)




💡 결론
클라이언트가 클래스의 세부적인 내용에 접근하지 않고도 다양한 객체를 쉽게 복제할 수 있는 기능을 제공하고자 할 때 프로토타입 패턴을 고려하면 좋겠다. 추가적으로 Java의 경우 복제 메서드를 동일하게 제공하기 위한 Cloneable 메서드를 제공하므로 프로토 타입 패턴 적용 시 고려해보자!

+) 프로토타입 패턴이 실무에서 언제, 어떻게 활용되는지 궁금해서 찾아봤다. 프로토타입 패턴을 실무에서 잘 사용하지 않는다는 의견이 대부분이었으며, 실무에서 유용히 활용한다는 사례는 쉽게 찾아보지 못했다. 추후 프로토타입을 적용하게 되는 경험이 생기거나 실무에서 활용하는 사례를 보게 되면 따로 기록해보겠다.

0개의 댓글