본문 바로가기
자바

디자인 패턴 4. 데코레이터 패턴 (Decorator Pattern)

by 호놀롤루 2022. 3. 12.

1. 개요

기존 뼈대(클래스)는 유지하면서, 이후 필요한 형태로 꾸밀 때 사용하는 패턴이다.

확장이 필요한 경우 상속의 대안으로도 사용한다. SOLID의 개방폐쇄 원칙(OCP), 의존역전 원칙(DIP)를 따른다.

 

에스프레소가 있다고 가정하고, 에스프레소에 물을 넣으면 아메리카노가 된다.

에스프레소에 물과 우유를 넣으면 카페라떼가 된다.

 

케이크에 초코를 바르면 초코케이크가 되고, 딸기를 넣으면 딸기케이크가 된다.

 

이런 식으로 원본을 유지하되, 어떤 것을 씌우거나 첨가하는 것으로 다른 형태로 확장하는 것을 데코레이터

패턴이라 한다.

 

 

2. 코드

 

package com.company.design.decorator;

public interface ICar {

    int getPrice();
    void showPrice();
}

다형성을 사용하기 위해 기초가 되는 인터페이스를 만든다.

package com.company.design.decorator;

public class Audi implements ICar {

    private int price;

    public Audi(int price) {
        this.price = price;
    }

    @Override
    public int getPrice() {
        return this.price;
    }


    @Override
    public void showPrice() {
        System.out.println("audi의 가격은 "+this.price+" 원 입니다.");
    }
}

Audi는 가격을 가지고, 생성자에서 들어온 파라미터의 값만큼 가격을 가진다.

getPrice()로 가격을 반환하고, showPrice()로 가격을 출력한다.

 

 

package com.company.design.decorator;

public class AudiDecorator implements ICar {

    protected ICar audi;
    protected String modelName;
    protected int modelPrice;

    public AudiDecorator(ICar audi, String modelName, int modelPrice) {
        this.audi = audi;
        this.modelName = modelName;
        this.modelPrice = modelPrice;
    }

    @Override
    public int getPrice() {
        return audi.getPrice() + modelPrice;
    }

    @Override
    public void showPrice() {
        System.out.println(modelName + "의 가격은 "+ getPrice() + " 원 입니다.");
    }
}

데코레이터 패턴이다. 멤버 변수는 3개가 있는데, 다형성을 사용하기 위해 인터페이스로 받은 audi, 케이크에서

초코를 바르듯이, 등급에 따라 구별하기 위한 modelName, 추가할 가격인 modelPrice가 있다.

생성자에서 3개 다 받고 멤버 변수에 집어넣는다.

 

getPrice를 하면 원래 생성해놓은 audi의 가격에, 모델의 값을 더한 값을 반환한다.

 

showPrice()로 모델명과 합산된 값을 반환한다.

 

package com.company.design.decorator;

public class A3 extends AudiDecorator {
    public A3(ICar audi, String modelName) {
        super(audi, modelName, 1000);
    }
}

A3 모델이다. AudiDecorator를 상속받고, 가격을 1000으로 했으니, 이 데코레이터를 사용하면 가격이 1000

추가되고 모델명이 달라질 것이다.

 

package com.company.design.decorator;

public class A4 extends AudiDecorator {
    public A4(ICar audi, String modelName) {
        super(audi, modelName, 2000);
    }
}

A4도 마찬가지다. 모델명 받고, 가격이 2000 추가된다.

 

package com.company.design.decorator;

public class A5 extends AudiDecorator {
    public A5(ICar audi, String modelName) {
        super(audi, modelName, 3000);
    }
}

얘도 마찬가지다. 모델명 받고, 가격이 3000 추가된다.

 

package com.company.design.decorator;

public class Main {
    public static void main(String[] args) {
        ICar audi = new Audi(1000);
        audi.showPrice();

        // a3
        ICar audi3 = new A3(audi, "A3");
        audi3.showPrice();

        // a4
        ICar audi4 = new A4(audi, "A4");
        audi4.showPrice();

        // a5
        ICar audi5 = new A5(audi, "A5");
        audi5.showPrice();
    }
}

실행 결과

audi의 가격은 1000 원 입니다.
A3의 가격은 2000 원 입니다.
A4의 가격은 3000 원 입니다.
A5의 가격은 4000 원 입니다.

 

결과적으로 audi를 전혀 건드리지 않았지만, audi와 별개로 모델과 가격을 추가할 수 있게 되었다.

댓글