Clean Code

[Design Pattern] 구조 패턴 - 데코레이터 패턴

yaini 2022. 3. 3. 23:57
반응형

데코레이터 패턴

주어진 상황 및 용도에 따라 객체에 대한 책임을 덧붙이는 패턴

기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 대안

자바는 다중 상속을 지원하지 않기 때문에 추가해야 할 기능의 종류가 많은 경우 데코레이터 패턴을 사용할 수 있다.

데코레이터 클래스와 데코레이터를 적용할 클래스는 합성 관계를 통해 표현된다.

합성(has-a) 관계

  • 생성자에서 필드에 대한 객체를 생성하는 경우
  • 전체 객체가 없어지면 부분 객체도 없어진다.
  • 상속에 의해 코드를 재사용하는 것 대신, 객체의 기능(인터페이스)를 호출하는 방식을 통해 재사용

전체 코드

public class Decorator {
    public static void main(String[] args){
        Wallet decoratedWallet = new ColorDecorator(
                new ZipperDecorator(new SimpleWallet())
        );
        decoratedWallet.custom();
    }
}

interface Wallet{
    void custom();
}

class SimpleWallet implements Wallet{

    @Override
    public void custom() {
        System.out.println("My Wallet");
    }
}

class WalletDecorator implements Wallet{
    private Wallet decoratedWallet;

    public WalletDecorator(Wallet decoratedWallet){
        this.decoratedWallet = decoratedWallet;
    }

    @Override
    public void custom() {
        decoratedWallet.custom();
    }
}

class ColorDecorator extends WalletDecorator{
    ColorDecorator(Wallet decoratedWallet){
        super(decoratedWallet);
    }

    @Override
    public void custom() {
        super.custom();
        System.out.println("Color My wallet");
    }
}

class ZipperDecorator extends WalletDecorator{
    ZipperDecorator(Wallet decoratedWallet){
        super(decoratedWallet);
    }

    @Override
    public void custom() {
        super.custom();
        System.out.println("Zip My wallet");
    }
}

코드로 보면 이해하기 더 쉬운데, 데코레이터 패턴을 적용하지 않고 Color+Zipper를 모두 데코레이트 해야 한다면 ColorZipper 클래스를 하나 더 생성해야 한다.

기능이 더 많아지면 클래스 경우의 수는 더 많아지게 된다. 이렇게 기능에 따라 각각 클래스를 생성하지 않아도 원하는 기능만 추가할 수 있게 해준다.

또한 상속 관계가 아닌 합성 관계를 사용하기 때문에 클래스 간의 결합도를 낮춰준다.

 

 

참고

https://ko.wikipedia.org/wiki/데코레이터_패턴
https://gmlwjd9405.github.io/2018/07/09/decorator-pattern.html
https://mantaray.tistory.com/69
반응형