티스토리 뷰

knowledge

[Java] Prototype 생성 패턴

글을 쓰는 개발자 2021. 11. 2. 21:48
반응형

1. GoF 디자인 패턴

의도

원형이 되는(prototypical) 인스턴스를 사용하여 생성할 객체의 종류를 명시하고, 이렇게 만든 견본을 복사해서 새로운 객체를 생성하는 것

동기

책에서 나온 예제를 요약하여 설명해보겠습니다. 원래 범용적으로 쓰이던 그래픽 프레임워크가 있는데, 새로 추가하고자 하는 음표와 보표에 대한 클래스를 넣고자 했을 때 그래픽 프레임 워크는  그래픽 관련 클래스를 상속 받은 서브 클래스를 필요로 하게 됩니다. 하지만 이렇게 되면 각 음표마다 클래스를 만들게 되는데 이러한 것을 해결하는 방법 중 하나가 '프로토 타입' 이라고 한다.
기본적으로 원형을 복제하고 setXyz 를 사용하여 값을 변형해 사용하는 방식을 쓴다면 클래스를 더 줄일 수 있다는 장점을 가질 수 있게 된다.

활용성

1. 인스턴스화할 클래스를 런타임에 지정할 때
2. 제품 클래스 계통과 병렬적으로 만드는 팩토리 클래스를 피하고 싶을 때
3. 클래스의 인스턴스들이 서로 다른 상태 조합 중에 어느 하나일 때 원형 패턴을 사용. 미리 원형으로 초기화해 두고, 나중에 이를 복제해서 사용하는 것이 매번 필요한 상태 조합의 값들을 수동적으로 초기화하는 것보다 더 편리할 수도 있다.

결과

1. 런타임에 새로운 제품을 추가하고 삭제할 수 있다.
2. 값들을 다양화함으로써 새로운 객체를 명세한다.(이 부분이 setter에 대한 내용. setter를 통해 원형을 기본으로 두고 그때 상황에 맞게 변수의 값을 지정함으로써 원형과 다른 객체를 얻는 행동)
3. 구조를 다양화함으로써 새로운 객체를 명세할 수 있다.
4. 서브클래스의 수를 줄일 수 있다.
5. 동적으로 클래스에 따라 응용프로그램을 설정할 수 있다.

 

예시

1. Building.java

public class Building {
    private final Room prototypeRoom;
    private final Wall prototypeWall;

    public Building(Room room, Wall wall){
        this.prototypeRoom = room;
        this.prototypeWall = wall;
    }

    public Room makeRoom(){
        return  prototypeRoom.getInstance();
    }

    public Wall makeWall(){
        return  prototypeWall.getInstance();
    }

}

Building.java가 'Client'에 해당하는 부분이다. (원형에 자기 자신의 복제를 요청하여 새로운 객체를 생성)

 

2. Room.java

public interface Room{
    Room getInstance();
}

 

3. Wall.java

public interface Wall{
    Wall getInstance();
}

Prototype으로서 자신을 복제하는 데 필요한 인터페이스를 정의

 

4.  NormalWall.java

public class NormalWall implements Wall{
    private String direction;

    @Override
    public String toString() {
        return direction+"쪽 "+"벽 입니다!";
    }

    public void setDirection(String direction) {
        this.direction = direction;
    }

    public NormalWall(){
        this("WEST");
    }

    public NormalWall(String direction){
        this.direction = direction;
    }

    public NormalWall(NormalWall room){ //복사 생성자
        this.direction = room.direction;
    }

    @Override
    public NormalWall getInstance() {
        return new NormalWall(this);
    }
}

NormalWall의 인스턴스처럼 원형으로 사용할 수 있는 객체는 반드시 getInstance() 연산을 제공해야 하고, 객체 복제를 위해 복사 생성자가 있어야 한다.

 

5.NormalRoom.java

public class NormalRoom implements Room{
    private int size;

    public void setSize(int size) {
        this.size = size;
    }

    @Override
    public String toString() {
        return "사이즈가 "+ size+"인 "+"방 입니다!";
    }

    public NormalRoom(){
        this(1);
    }

    public NormalRoom(int size){
        this.size = size;
    }

    public NormalRoom(NormalRoom room){
        this.size = room.size;
    }

    @Override
    public NormalRoom getInstance() {
        return new NormalRoom(this);
    }
}

 

 

Test를 통해 사용하는 법 엿보기

class SimpleTest {

    @Test
    void test_프로토타입(){
        Room room = new NormalRoom();
        NormalWall wall = new NormalWall();
        Building building = new Building(room,wall); // Client
        NormalWall customWall = (NormalWall) building.makeWall();
        customWall.setDirection("EAST"); // 원형을 가져와서 변형한다.
        NormalRoom customRoom = (NormalRoom) building.makeRoom();
        customRoom.setSize(3); // 원형을 가져와서 변형한다.
        System.out.println(customWall);
        System.out.println(customRoom);

    }
}

참고: GoF 디자인 패턴

반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함