final클래스의 확장? - 데코레이터

ttomy·2023년 3월 13일
0

https://codingnuri.com/seven-virtues-of-good-object/
위 포스팅을 읽고 final클래스를 상속 받을 수 없지만, 확장이 데코레이터 패턴이라는 방식으로 가능하다는 것을 알았다.
이건 어떤 방식일까?

새로운 구현체가 확장하고자 하는 클래스를 인스턴스 변수로 가지고, 이를 통해 기능을 확장할 수 있다.

예를 들어 아래 그림과 같이 기본 요금에 대해 추가 거리에 따라 요금을 다르게 계산하고 싶다면 basicFare을 확장하는 distanceOverFare는 변수로 가진 BasicFare의 caculate에 추가 작업을 거리에 따른 요금을 계산할 수 있다.

  • 예시
    state ->인터페이스
    running - finished -> state상속한 추상클래스
    stay - blackjack -> finished를 상속한 구현 클래스

예를 들어,(현실적으로 없을 요구사항이지만) 블랙잭 카드게임에서 stay클래스를 확장해 이름이 3글자 이상이라면 배팅결과를 2배로 늘리는 Eventstay를 만들고자 하면, 아래와 같은 시도를 할 수 있다.

//decorator
public abstract class Decorator implements State { 
    protected final Finished target; 
    
    protected Decorator(Cards cards) { 
        this.target = new Stay(cards); 
    } 
    
    protected Result playDelegate(Hand dealer) { return target.play(dealer); } 
}


//기존의 stay
public final class Stay extends Finished {
    protected Stay(final Cards cards) {
        super(cards);
    }

    @Override
    public Result play(Hand dealer) {
        Cards dealerCards = dealer.cards();
        if (cards().isScoreOver(dealerCards)) {
            return Result.WIN;
        }
        if (cards().isScoreUnder(dealerCards)) {
            return Result.LOSE;
        }
        return Result.DRAW;
    }
}

// 확장된 stay
public final class EventStay extends Decorator {

    private final Finished stay;
    private final Name name;
    
    protected EventStay(final Cards cards, Name name) {
        super(cards);
        this.name = name
    }

    @Override
    public Result play(Hand dealer) {
         Result result = super.playDelegate(dealer);
         if (name.size() >= 3) {
         return Result.multiply(result, 2);
        }
        return result;
    }
}

데코레이션 패턴이라는 이름이 붙었지만 사실 조합을 통해 기존 클래스를 확장하는 방식으로 생각하면 될 것 같다.

REFERENCE

https://bugoverdose.github.io/development/decorator-pattern-implementation-and-limitations/

0개의 댓글