2022-03-27 @이영훈
데코레이터 패턴
데코레이터 패턴은 주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴입니다.
롤 챔피언과 아이템 예제
롤 챔피언 (아리, 카이사)가 상점에서 아이템 (도란의 반지, 메자이, 마나무네)을 사는 예제입니다.
챔피언들은 어떤 아이템이든 순서와 상관없이 장착할 수 있습니다. 즉, 챔피언들은 아이템을 유연하게, 동적으로 장착할 수 있습니다.
아이템은 롤 챔피언을 변수로 가지고 있고, 장착하는 순간 해당 챔피언의 물리 공격력과 마법 공격력을 올려줍니다.
롤 챔피언과 아이템 예제 구현
롤 챔피언 인터페이스를 만듭니다.
public interface LolChampion {
public int getAttackDamage();
public int getAbilityPower();
public String getName();
}
Java
복사
롤 챔피언 인터페이스를 구현하여 아리와 카이사 챔피언을 구현합니다.
public class Kaisa implements LolChampion {
private int attackDamage = 32;
private int abilityPower = 30;
public Kaisa() {
}
@Override
public int getAttackDamage() {
return attackDamage;
}
@Override
public int getAbilityPower() {
return abilityPower;
}
@Override
public String getName() {
return "Kaisa";
}
}
Java
복사
아리 구현체입니다.
public class Ahri implements LolChampion {
private int attackDamage = 30;
private int abilityPower = 34;
public Ahri() {
}
@Override
public int getAttackDamage() {
return attackDamage;
}
@Override
public int getAbilityPower() {
return abilityPower;
}
@Override
public String getName() {
return "Ahri";
}
}
Java
복사
롤 아이템 인터페이스를 만듭니다. 롤 아이템은 롤 챔피언을 인스턴스 변수로 가집니다. abstract class로 만들어 생성자까지 선언하겠습니다.
롤 아이템으로 만든 객체를 다시 롤 챔피언에게 반환하기 위해서 롤 아이템도 롤 챔피언을 구현(implements) 받습니다. 이 내용은 아래에 호출하는 코드를 보면 이해가 더 빠릅니다.
public abstract class LolItem implements LolChampion {
LolChampion lolChampion;
public LolItem(LolChampion lolChampion) {
this.lolChampion = lolChampion;
}
abstract public String getName();
}
Java
복사
롤 아이템을 구현합니다. 도란의 반지, 메자이, 마나무네 3개의 아이템을 구현해 만듭니다.
도란의 반지 구현 부분입니다.
public class DoranRing extends LolItem {
private final int additionalAttackDamage = 0;
private final int additionalAbilityPower = 15;
public DoranRing(LolChampion lolChampion) {
super(lolChampion);
}
@Override
public int getAttackDamage() {
return lolChampion.getAttackDamage() + additionalAttackDamage;
}
@Override
public int getAbilityPower() {
return lolChampion.getAbilityPower() + additionalAbilityPower;
}
@Override
public String getName() {
return lolChampion.getName() + " + 💍도란링";
}
}
Java
복사
메자이 구현 부분입니다.
public class Mejai extends LolItem {
private final int additionalAttackDamage = 0;
private final int additionalAbilityPower = 20;
public Mejai(LolChampion lolChampion) {
super(lolChampion);
}
@Override
public int getAttackDamage() {
return lolChampion.getAttackDamage() + additionalAttackDamage;
}
@Override
public int getAbilityPower() {
return lolChampion.getAbilityPower() + additionalAbilityPower;
}
@Override
public String getName() {
return lolChampion.getName() + " + 📚메자이";
}
}
Java
복사
마나무네 구현 부분입니다.
public class Manamune extends LolItem {
private final int additionalAttackDamage = 35;
private final int additionalAbilityPower = 0;
public Manamune(LolChampion lolChampion) {
super(lolChampion);
}
@Override
public int getAttackDamage() {
return lolChampion.getAttackDamage() + additionalAttackDamage;
}
@Override
public int getAbilityPower() {
return lolChampion.getAbilityPower() + additionalAbilityPower;
}
@Override
public String getName() {
return lolChampion.getName() + " + 🗡마나무네";
}
}
Java
복사
롤 챔피언과 아이템 호출
아리에게 도란의 반지와 메자이 아이템을 장착시킵니다.
그리고 카이사에게는 도란의 반지와 마나무네 아이템을 장착시킵니다.
챔피언들을 부모 클래스(여기에서는 LolChampion)으로 타입을 지정하였습니다. 아이템을 장착시킨 후에 해당 챔피언 인스턴스에게 다시 반환합니다. 이를 위해서 롤 아이템들을 롤 챔피언을 구현받도록 하였습니다.
public class DecoratorApplication {
public static void main(String[] args) {
// 🦊 아리 + 💍 도란링 + 📚 메자이
LolChampion ahri = new Ahri();
ahri = new DoranRing(ahri);
ahri = new Mejai(ahri);
System.out.println("👊 아리 물리 공격력 = " + ahri.getAttackDamage());
System.out.println("🪄 아리 마법 공격력 = " + ahri.getAbilityPower());
// 👊 아리 물리 공격력 = 30
// 🪄 아리 마법 공격력 = 69
// 🧙 카이사 + 💍 도란링 + ⚔️ 마나무네
LolChampion kaisa = new Kaisa();
kaisa = new DoranRing(kaisa);
kaisa = new Manamune(kaisa);
System.out.println("👊 카이사 물리 공격력 = " + kaisa.getAttackDamage());
System.out.println("🪄 카이사 마법 공격력 = " + kaisa.getAbilityPower());
// 👊 카이사 물리 공격력 = 67
// 🪄 카이사 마법 공격력 = 45
}
}
Java
복사
Ref.
example inspired by. Tony