티스토리 뷰

Product Manager

Strategy Pattern #2

하루10분 2007. 2. 15. 09:13
반응형
출처 : www.DefineJava.net


스트래티지 패턴 두번째 시간이다.
우선 저번에 필자가 냈던 문제를 생각해보자~
1. 개발자는 로봇 게임을 제작중이다.
2. 게임을 더 재밋게 하기 위하여 개발자는 특수기능을 넣을려고 한다.
3. 현재는 특수기능이 "날 수 있는 기능" 밖에 없지만 이후에는 여러가지 기능이 추가 될 수도 있다.

해결방법으로 생각했던 상속을 사용하게 되면 현재 날아다니는 기능은 구현이 가능하나 나중에 특수기능이 더 많이 추가 된다면 문제가 발생한다.
그리고 또 오버라이딩을 한다면 로봇 수가 늘어 나게 될 때 개발자는 죽도록 노가다 코딩을 해야 될 것 이다.

이제 조금 더 쉽게 이 문제를 해결할 수 있는 방법을 생각 해 보자.
필자는 이 문제의 해답은 인터페이스를 잘 사용하므로써 해결 가능하다고 생각했다.(원래 답을 알고있으니....-_-)

이 것을 확실히 알아야 한다. 지금 추가하려고 하는것은 특수 기능이다. 특수 기능 중 한가지가 "날아다니는 기능" 이다.
여기서 생각할 수 있는 것은 특수기능이라는 틀을 만들고 그 안에 "날아다니는 기능"을 넣으면 된다는 것이다.

자 클래스 다이어그램을 보면 쉽게 이해 할 수 있을것이다.

사용자 삽입 이미지

아하~ 하고 이해가 오는 사람은 객체지향 개념을 알고 있는 사람일 것이다. "이게 머야?" 또는 "이렇게 해봣자 코드가 늘어나는 것은 같잖아" 이렇게 생각하는 사람은

아직 객체지향을 잘 이해하지 않고 있다.
자! 다이그램을 보면 AbilityBehavior라는 인터페이스를 Fly라는 클래스가 Implement 하고 있다. 이것이 의미하는것은 AbilityBehavior라는 큰 모델이 있고 그 모델이

할 수있는 일(Method)를 구현해야 된다는것과 AbilityBehavior ability = new Fly(); 이런식으로 선언이 가능하다는 것이다.

이쯤되면 스트래티지 패턴이 어떤 문제점을 해결 할 수있는 패턴인지 알 수 있을것이다.
특수기능에 숨는 기능을 넣어 보자.
AbilityBehavior 인터페이스를 Hide라는 클래스가 상속 받아 구현 하면 될것이다.

이제 문제점이 해결 되었는가? (모르겠으면 소스를 보는 것이 이해에 도움이 될듯 싶다);

이와 같이 구현을 한다면 로봇 객체를 선언할 때 각 로봇에 특수 기능을 줄수있다. 물론 특수 기능 변경을 하는 setAbilityBehavior라는 메소드를 만들어서 동적으로도 변경을 할 수있다.

전체적인 소스코드를 첨부 해서 올리니 한번씩 봐보길 바라며 끝으로 어떻게 하면 더욱더 적용이 가능할지 생각해보길 바란다.

디아블로같은 게임을 생각해 보아도 좋다. 갑옷이라는 인터페이스를 만들고 그 갑옷을 Implement한 클래스만 입을수 있다.
이것도 스트래티지 패턴을 이용해서 구현이 가능하다. 조금만 더 생각해 보면 알 수 있을 것이다.
set갑옷 이라는 메소드만 한개 만들어서 갑옷을 바꿔주면 된다.

일이 밀려서 몇일간 한가지를 쓰다보니 말이 앞뒤가 안 맞는 부분이 많아 졌다. 아마도 디자인패턴을 공부하려는 사람 정도면 소스만 보고도 이해 할 수 있을거라 생각한다~

// 소스
package strategy;

public interface AbilityBehavior {

  public void setName(String name);
  public void ability();
}

package strategy;

public class Fly implements AbilityBehavior {

  public String name;
  public void setName(String name) {
   // 어빌리티 이름을 지정.
   this.name = name;
  }

  public void ability() {
   System.out.println("날기시작합니다.");
  }
}

package strategy;

public class Hide implements AbilityBehavior {

  public String name;
  public void setName(String name) {
   this.name = name;
  }

  public void ability() {
   System.out.println("숨었다~ 안보이지룽-.-");
  }
}

package strategy;

public abstract class Robot {
 
  String name;
  AbilityBehavior ability;
 
  public abstract void display();
 
  public void turn(int rec) {
   System.out.println(name + "로봇이 "+rec+"만큼 돌았습니다.");
  }

  public void attack() {
   System.out.println(name + "로봇이 공격합니다.");
  }

  public void move(int x, int y) {
   System.out.println(name + "로봇이 "+x+","+y+" 좌표로 이동합니다.");
  }

  public Robot(AbilityBehavior ability, String name) {
   this.ability = ability;
   this.name = name;
  }
 
  public void performAbility() {
   ability.ability();
  }
 
}

package strategy;

class TaekwonVRobot extends Robot{

  public TaekwonVRobot(AbilityBehavior ability)
  {
   super(ability, "마징가Z");
  }
 
  public void display() {
   System.out.println("저는 " + name + " 로봇이랍니다.");
  }
}

package strategy;

class MajinggaRobot extends Robot{
 
  public MajinggaRobot(AbilityBehavior ability)
  {
   super(ability,"마징가Z");
  }
 
  public void display() {
   System.out.println("저는 " + name + " 로봇이랍니다.");
  }
}

package strategy;

class FreedomRobot extends Robot{
 
  public FreedomRobot(AbilityBehavior ability)
  {
   super(ability , "프리덤");
  }
 
  public void display() {
   System.out.println("저는 " + name + " 로봇이랍니다.");
  }
}

package strategy;

public class RobotMain
{

 public static void main(String[] args)
 {
  Robot robot1 = new FreedomRobot(new Fly());  // 날아다니는 프리덤.
  Robot robot2 = new FreedomRobot(new Hide()); // 숨는기능의 프리덤.
 
  Robot robot3 = new TaekwonVRobot(new Fly()); // 숨는기능의 태권 V.
  Robot robot4 = new MajinggaRobot(new Hide()); // 숨는기능의 마징가.
 
  robot1.display();
  robot1.performAbility();
 
  robot2.display();
  robot2.performAbility();
 
  robot3.display();
  robot3.performAbility();
 
  robot4.display();
  robot4.performAbility();
 }

}

반응형
댓글