데코레이터 패턴

이정석·2023년 6월 23일
0

디자인패턴

목록 보기
22/23

데코레이터 패턴이란?

동적으로 객체에 책임을 추가할수 있도록 한다. 즉, 객체의 결합을 통해 기능을 동적으로 유연하게 확장 할 수 있게 해주는 패턴이다.


문제상황

보통 RPG게임에서 스킬의 레벨이 오르면 스킬트리와 같은 기능을 통해 스킬을 자유롭게 확장이 가능하다.
1. 기본 캐릭터의 스킬은 다음과 같다.

public interface Character {
    String getSkills();
}

public class BasicCharacter implements Character {
    @Override
    public String getSkills() {
        return "Basic attack";
    }
}

2. 불속성(Fire)스킬과 얼음속성(Ice)스킬로 확장한다면 다음과 같이 만들 수 있다.

public class FireMage implements Character {
    @Override
    public String getSkills() {
        return "Basic attack, Fireball";
    }
}

public class IceMage implements Character {
    @Override
    public String getSkills() {
        return "Basic attack, Ice shard";
    }
}

3. 이후에 스킬이 더 확장되어서 연쇄(Explosive)스킬로 확장된다면 다음과 같은 스킬을 추가해야 한다.

public class ExplosiveFireMage implements Character {
    @Override
    public String getSkills() {
        return "Basic attack, Fireball, Chain Explosion";
    }
}

public class ExplosiveIceMage implements Character {
    @Override
    public String getSkills() {
        return "Basic attack, Ice shard, Chain Explosion";
    }
}

위 상황은 스킬을 확장하는 과정의 모든 경우에 대한 구현이 필요한 상황이다. 이런 경우는 구현해야 할 코드의 양이 매우 많아지고 스킬의 추가, 변경, 삭제가 어려워진다.

스킬의 확장을 하나의 객체로 만들어 객체의 결합을 동적으로 바꾸게 하자


구조

  1. Component: 데코레이터 패턴에 포함된 모든 객체가 구현할 메서드를 정의한 클래스로 Component를 사용하는 Client는 데코레이터가 추가된 객체와 기존 객체를 동일하게 사용한다.
  2. ConcreteComponent: Component를 구현한 클래스로 기본적인 기능을 수행하는 객체이다.
  3. Decorator: Component에 추가할 공통기능을 제공하는 클래스로 클라이언트가 요청한 operation을 상위 Component에 전달한다.
  4. ConcreteDecorator: Decorator를 상속해 특정 기능을 구현한 클래스이다.

코드(JAVA)

1. Character

public interface Character {
    String getSkills();
}

public class BasicCharacter implements Character {
    @Override
    public String getSkills() {
        return "Basic attack";
    }
}

BasicCharacter는 ConcreteComponent에 해당하는 기본 기능을 구현한 클래스이다.

2. SkillDecorator

public abstract class SkillDecorator implements Character {
    protected Character character;

    public SkillDecorator(Character character) {
        this.character = character;
    }

    @Override
    public String getSkills() {
        return character.getSkills();
    }
}

Decorator에 해당하는 클래스로 Component(Character)의 operation을 실행하도록 정의된 추상클래스이다.

3. Fireball, IceShard, ChainExplosion Decorator

public class FireballDecorator extends SkillDecorator {
    public FireballDecorator(Character character) {
        super(character);
    }

    @Override
    public String getSkills() {
        return super.getSkills() + ", Fireball";
    }
}

public class IceShardDecorator extends SkillDecorator {
    public IceShardDecorator(Character character) {
        super(character);
    }

    @Override
    public String getSkills() {
        return super.getSkills() + ", Ice shard";
    }
}

public class ChainExplosionDecorator extends SkillDecorator {
    public ChainExplosionDecorator(Character character) {
        super(character);
    }

    @Override
    public String getSkills() {
        return super.getSkills() + ", Chain Explosion";
    }
}

ConcreteDecorator에 해당하는 클래스로 각각 불속성, 얼음속성, 연쇄에 대한 기능을 추가하는 Decorator이다. ConcreteDecorator는 다음과 같은 단계로 동작한다.

1. 생성자에서 상위클래스의 생성자로 상위 Component를 설정한다.
2. 상위 Component의 operation(getSkills)를 먼저 실행 한 후 해당 Decorator에 수행할 연산을 실행한다.

Component의 생성은 Client에서 어떻게 할까

만약 불속성 연쇄 스킬을 만들고자 할 때 Client는 어떻게 Character를 생성해야 할까?

결국, 기능을 수행하는 최종 객체는 ConcreteComponent에 해당하는 BasicCharacter이다. 즉, 최상위 클래스는 BasicCharacter이고 아래에 FireballDecoratorChainExplosionDecorator있는 구조여야 한다.

Character fireExplosionCh = new ChainExplosionDecorator(new FireballDecorator(new BasicCharacter()));

위와 같이 하면 최상위 클래스는 BasicCharacter이 생성되고, 이후에 FireballDecoratorChainExplosionDecorator가 순서대로 생성되어 밑에 위치하는 구조가 된다.

profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글