Player가 있고 Player는 GameLevel 속성을 가집니다. 각 GameLevel 단계 마다 run(), jump(), turn() 세 가지 기능이 업그레이드 됩니다.
초보자 레벨 : 천천히 달립니다. run() 만 가능
중급자 레벨 : 빠르게 달리고, 점프할 수 있습니다. run(), jump() 가능
고급자 레벨 : 엄청 빠르게 달리고, 높게 점프하고, 턴할 수 있습니다. run(), jump(), turn() 가능
Player는 한번에 하나의 레벨 상태만을 가질 수 있습니다.
Player가 play() 중에 레벨에 있는 go(int count) 라는 메서드를 호출하면 run() 하고 count 횟수 만큼 jump() 하고 turn() 합니다. 다음 클래스 다이어그램을 참고하여 각 레벨에서 go() 가 호출 될때 다음과 같이 출력 되도록 하세요
일단 다이어그램을 보니, PlayerLevel 을 상위클래스로 하여 Beginner, Advanced, Super 클래스를 상속하여 생성하였음을 생각할 수 있다.
또한 PlayerLevel 클래스를 활용하여 Player 클래스를 만들어야한다.
package ch09.player;
public abstract class PlayerLevel {
public abstract void run();
public abstract void jump();
public abstract void turn();
public abstract void showLevelMessage();
final public void go(int count) {
run();
for(int i = 0 ; i < count; i++) {
jump();
}
turn();
}
}
PlayerLevel 은 추상클래스로 구현하였다. 대부분의 메서드는 abstract 메서드 (추상 메서드) 로 선언하여 상속받을 클래스들에서 오버라이딩 될 수 있게 하였다.
그러나 전체적으로 똑같이 공유하게될 메서드인 go 메서드는 final 로 선언해주어 상속될 수 없게 해주었는다.
go메서드의 내용은 int로 받은 숫자만큼 jump 메서드를 반복해준다.
package ch09.player;
public class Beginner extends PlayerLevel {
@Override
public void run() {
System.out.println("천천히 달립니다.");
}
@Override
public void jump() {
System.out.println("jump 못하지롱.");
}
@Override
public void turn() {
System.out.println("turn 못하지롱");
}
@Override
public void showLevelMessage() {
System.out.println("****** 초급자 레벨 *******");
}
}
package ch09.player;
public class Advanced extends PlayerLevel {
@Override
public void run() {
System.out.println("빨리 달립니다.");
}
@Override
public void jump() {
System.out.println("높이 jump 합니다.");
}
@Override
public void turn() {
System.out.println("turn 못하지롱");
}
@Override
public void showLevelMessage() {
System.out.println("****** 중급자 레벨 *******");
}
}
package ch09.player;
public class Advanced extends PlayerLevel {
@Override
public void run() {
System.out.println("빨리 달립니다.");
}
@Override
public void jump() {
System.out.println("높이 jump 합니다.");
}
@Override
public void turn() {
System.out.println("turn 못하지롱");
}
@Override
public void showLevelMessage() {
System.out.println("****** 중급자 레벨 *******");
}
}
위와 같이 오버라이딩 하였다. 단순한 출력으로 오버라이딩 한 부분이다.
package ch09.player;
public class Player {
private PlayerLevel level;
Player() {
level = new Beginner();
level.showLevelMessage();
}
public PlayerLevel getLevel() {
return level;
}
public void upgradeLevel(PlayerLevel level) {
this.level = level;
level.showLevelMessage();
}
public void play(int count) {
level.go(count);
}
}
Player 클래스는 우선 PlayerLevel 타입의 level을 필드로 갖는다.
그리고 생성자를 통해 처음 Player 객체를 생성해주었을 때, Beginner 객체가 생성되고 level에 대입될 수 있게 하였다.
그리고 upgradeLevel을 통하여 객체를 교체해줄 수 있었다 (형변환)
마지막으로 play(int count) 통해서 go메서드를 호출해주었다. (fianl로 선언되어 있어서 변경 불가능)
package ch09.player;
public class MainBordPlay {
public static void main(String[] args) {
Player player = new Player();
player.play(1);
player.upgradeLevel(new Advanced());
player.play(2);
player.upgradeLevel(new Super());
player.play(3);
}
}
/*
****** 초급자 레벨 *******
천천히 달립니다.
jump 못하지롱.
turn 못하지롱
****** 중급자 레벨 *******
빨리 달립니다.
높이 jump 합니다.
높이 jump 합니다.
turn 못하지롱
****** 고급자 레벨 *******
아주 빠르게 달립니다.
아주 높이 jump 합니다.
아주 높이 jump 합니다.
아주 높이 jump 합니다.
turn 합니다.
*/
위와같이 실행시켜 주었다.
생성자를 활용하여 ****레벨**** 부분을 출력해주었고
upgradeLevel의 매개변수로 객체를 넣어서 형변환을 해준 것에 유의