Java & Kotlin
[Java 객체지향] 추상 클래스와 템플릿 메서드 활용 예제 프로그램 (GameLevel 구현)
Sue
2022. 2. 2. 15:56
Player가 있고, Player는 GameLevel 속성을 가진다. 각 GameLevel 단계 마다 run(), jump(), turn() 세가지 기능이 업그레이드 된다.
Beginner : run()만 가능
Super : run(), jump() 가능
Advanced : run(), jump(), turn() 가능
Player는 한번에 하나의 레벨 상태만을 가질 수 있다.
Player가 play() 중에 레벨에 있는 go(int count)라는 메서드를 호출하면 run(), 횟수만큼 jump(), turn() 한다.
클래스 다이어그램
- PlayerLevel는 abstract class로 선언한다.
- go(int) 메서드는 템플릿 메서드로 구현하여 다른 클래스에서 순서를 변경할 수 없도록 한다.
- 각 레벨의 클래스는 PlayerLevel 추상 클래스를 상속받는다.
- PlayerLevel에서 선언한 추상 메서드를 각 레벨의 클래스에서 기능에 맞게 구현한다.
- Player는 하나의 level만을 가지므로 디자인 패턴 중 state pattern이 적용된다.
출력 결과
source hierarchy
DAO 소스 계층을 떠올리면서 비슷하게 만들었다.
PlayerLevel.java
package gamelevel.level;
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) {
showLevelMessage();
run();
for( int i = 0 ; i < count ; i ++ ) {
jump();
}
turn();
}
}
각 레벨 클래스에서 추상 메서드 구현
BeginnerLevel.java
package gamelevel.level.beginnerlevel;
import gamelevel.level.PlayerLevel;
public class BeginnerLevel extends PlayerLevel{
@Override
public void run() {
System.out.println("천천히 달립니다.");
}
@Override
public void jump() {
System.out.println("점프 못하지롱");
}
@Override
public void turn() {
System.out.println("turn 못하지롱");
}
@Override
public void showLevelMessage() {
System.out.println("******초급자 레벨입니다******");
}
}
SuperLevel.class
package gamelevel.level.superlevel;
import gamelevel.level.PlayerLevel;
public class SuperLevel extends PlayerLevel{
@Override
public void run() {
System.out.println("빨리 달립니다.");
}
@Override
public void jump() {
System.out.println("높이 점프 합니다.");
}
@Override
public void turn() {
System.out.println("turn 못하지롱");
}
@Override
public void showLevelMessage() {
System.out.println("******중급자 레벨입니다******");
}
}
AdvancedLevel.java
package gamelevel.level.advancedlevel;
import gamelevel.level.PlayerLevel;
public class AdvancedLevel extends PlayerLevel{
@Override
public void run() {
System.out.println("엄청 빠르게 달립니다.");
}
@Override
public void jump() {
System.out.println("아주 높이 점프합니다.");
}
@Override
public void turn() {
System.out.println("turn 합니다.");
}
@Override
public void showLevelMessage() {
System.out.println("******고급자 레벨입니다******");
}
}
Player.java
- level은 Player당 하나씩 가지고 있어야 하므로 변수를 private으로 설정하고 내부에서만 조작이 가능하도록 한다.
- private 변수에 대한 getter와 setter 대신 upgradeLevel 메서드로 level을 변경해줄 수 있다.
play 메서드에 매개변수가 없는 줄 알고 헤맸다리..
package gamelevel.player;
import gamelevel.level.PlayerLevel;
public class Player {
private PlayerLevel level; // level 변수 private으로 정의
public PlayerLevel getLevel() {
return level;
}
public void upgradeLevel(PlayerLevel level) {
this.level = level;
}
public void play(int count) {
level.go(count);
}
}
PlayerTest.java
package gamelevel;
import gamelevel.level.PlayerLevel;
import gamelevel.level.advancedlevel.AdvancedLevel;
import gamelevel.level.beginnerlevel.BeginnerLevel;
import gamelevel.level.superlevel.SuperLevel;
import gamelevel.player.Player;
public class PlayerTest {
public static void main(String[] args) {
PlayerLevel beginnerLevel = new BeginnerLevel();
PlayerLevel superLevel = new SuperLevel();
PlayerLevel advancedLevel = new AdvancedLevel();
Player p1 = new Player();
Player p2 = new Player();
Player p3 = new Player();
p1.upgradeLevel(beginnerlevel);
p1.play(1);
p2.upgradeLevel(superlevel);
p2.play(2);
p3.upgradeLevel(advancedLevel);
p3.play(3);
}
}
※ 수정
- Player 객체를 만들 때 초기화하는 default 생성자를 넣어주는게 좋다. (beginner level)
- beginner level을 upgradeLevel로 설정할 필요 없음
Player.java
default 생성자 추가
public Player() {
level = new BeginnerLevel();
}
PlayerTest.java
- BeginnerLevel 객체 생성하는 부분과 upgradeLevel 부분을 제거해주었다.
package gamelevel;
import gamelevel.level.PlayerLevel;
import gamelevel.level.advancedlevel.AdvancedLevel;
import gamelevel.level.beginnerlevel.BeginnerLevel;
import gamelevel.level.superlevel.SuperLevel;
import gamelevel.player.Player;
public class PlayerTest {
public static void main(String[] args) {
PlayerLevel superLevel = new SuperLevel();
PlayerLevel advancedLevel = new AdvancedLevel();
Player p1 = new Player();
Player p2 = new Player();
Player p3 = new Player();
p1.play(1);
p2.upgradeLevel(superlevel);
p2.play(2);
p2.upgradeLevel(advancedLevel);
p2.play(3);
}
}