티스토리 뷰

728x90
반응형

프로토 타입 패턴이란?


  • 기존 인스턴스를 복제하여 새로운 인스턴스를 만드는 방법입니다.
  • 프로토 타입 패턴은 객체를 생성하는데 비용이 많이 들고, 비슷한 객체가 이미 있는 경우에 사용되는 생성 패턴 중 하나입니다. 즉 프로토 타입 패턴은 원본 객체를 새로운 객체에 복사하여 필요에 따라 수정하는 원리를 제공합니다.
  • java에서는 대표적으로 clone() 메서드를 제공하고 있습니다.

 

객체 생성
  • 프로토 타입 패턴을 설명하기 전에 객체 생성에 대해 간단히 설명 드리겠습니다.
  • 객체를 생성하기 위해서는 먼저 클래스의 선언이 필요하며, 선언된 클래스를 기반으로 객체를 생성합니다. 객체는 선언된 클래스의 인스턴스화를 통하여 메모리에 적재가 되며 여기서 객체를 만드는 일반적인 방법은 new 키워드가 유일하며, new 키워드를 통해 선언한 클래스의 객체를 생성합니다.

 

얕은 복사와 깊은 복사
  • 얕은 복사 
    • 원본 객체와 복사 객체가 같은 대상을 참조하고 있으므로 어느 하나의 값이 변경되면 둘다 반영됨
  • 깊은 복사
    • 원본 객체를 복사하여 새로운 복사 객체를 만들때 새로운 영역에 할당하여 복사합니다.
    • 원본 객체와 복사 객체는 서로 다른 대상을 참조하고 있기 때문에 어느 하나 값이 변경되더라도 다른 하나에 영향을 미치지 않습니다.
    • 자바에서는 Cloneable이라는 마커 인터페이스를 활용하여 깊은 복사가 가능합니다.

 

클래스 다이어 그램


Prototype의 역할
  • 인스턴스를 복사하여 새로운 인스턴스를 만들기 위한 메서드를 선언합니다.
ConcretePrototype의 역할
  • Prototype의 구현클래스로써 새로운 인스턴스를 만드는 메서드를 실제로 구현
Client
  • 인스턴스 복사 메서드를 활용하여 새로운 인스턴스를 만듭니다.

 

예제 구조


 

Prototype의 역할 인터페이스
// Prototype의 인터페이스
public interface SmartPhone extends Cloneable {

    void initBattery(String text);
    void initCpu(String text);
    SmartPhone createClone();
}

 

ConcretePrototype의 역할 클래스
  • 인스턴스를 복사하여 새로운 인스턴스를 만드는 메서드를 실제로 구현합니다.
// 애플 스마트폰
public class AppleSmartPhone implements SmartPhone{

    @Override
    public void initBattery(String text) {
        System.out.println("삼성 휴대폰 배터리의 효율 " + text);
    }

    @Override
    public void initCpu(String text) {
        System.out.println("삼성 휴대폰 cpu의 효율 " + text);
    }

    @Override
    public SmartPhone createClone() {
        SmartPhone smartPhone = null;

        try {
            smartPhone = (SmartPhone) clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return smartPhone;
    }
}


// 삼성 스마트폰
public class SamsungSmartPhone implements SmartPhone{

    @Override
    public void initBattery(String text) {
        System.out.println("삼성 휴대폰 배터리의 효율 " + text);
    }

    @Override
    public void initCpu(String text) {
        System.out.println("삼성 휴대폰 cpu의 효율 " + text);
    }

    @Override
    public SmartPhone createClone() {
        SmartPhone smartPhone = null;

        try {
            smartPhone = (SmartPhone) clone();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return smartPhone;
    }
}

 

Client의 역할
  • 인스턴스를 복사하는 메서드를 이용해 새로운 인스턴스를 만듭니다.
public enum Person {
    APPLE,
    SAMSUNG
}

// Client의 역할을 하는 클래스
public class SmartPhoneStore {

    private Map<Person, SmartPhone> store = new HashMap<>();

    public void save(Person person) {
        SmartPhone smartPhone = null;

        if (person == Person.APPLE) {
            smartPhone = new AppleSmartPhone();
        }

        if (person == Person.SAMSUNG) {
            smartPhone = new SamsungSmartPhone();
        }
        store.put(person, smartPhone);
    }

    public SmartPhone buy(Person person){
        SmartPhone smartPhone = store.get(person);

        return smartPhone.createClone();
    }
}

 

실행 테스트
public class Example {
    public static void main(String[] args) {
        SmartPhoneStore smartPhoneStore = new SmartPhoneStore();
        smartPhoneStore.save(Person.APPLE);
        smartPhoneStore.save(Person.SAMSUNG);

        SmartPhone apple = smartPhoneStore.buy(Person.APPLE);
        SmartPhone copyApple = apple; // 얕은 복사
        SmartPhone deepApple = smartPhoneStore.buy(Person.APPLE); // 깊은 복사
        SmartPhone samsung = smartPhoneStore.buy(Person.SAMSUNG);

        apple.initBattery("100% 효율");
        apple.initCpu("M1 cpu");

        samsung.initBattery("100% 효율");
        samsung.initCpu("Intel cpu");

        System.out.println("apple.hashCode() = " + apple.hashCode());
        System.out.println("copyApple.hashCode() = " + copyApple.hashCode());
        System.out.println("deepApple.hashCode() = " + deepApple.hashCode());
        System.out.println("samsung.hashCode() = " + samsung.hashCode());

    }
}

 

장점
  • 복잡한 객체를 만드는 과정을 은닉할 수 있습니다.
  • 새로운 객체를 만드는 과정보다 기존 객체를 복사해서 만드는게 시간 또는 메모리적인 측면에서 효율적입니다.
단점
  • 복잡한 객체를 만드는 과정 자체가 복잡할 수 있습니다.

 

728x90
반응형