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