-
Java - 추상 클래스(템플릿 메서드 응용하기)4개발언어/JAVA 2023. 11. 4. 07:05
템플릿 메서드 응용하기
클래스의 기능과 관계
if(level == beginner) //beginner 기능구현 else if(level == advanced) //advanced 기능구현 else if(level == super) //super 기능구현
간단하게 생각하면 Player 클래스를 만들고 현재 player의 레벨에 따라 if 조건문으로 코드를 구현하면 된다. 의사 코드(pseudo code)로 작성하면 위 코드와 같다. 그런데 위와 같이 구현하면 level 수만큼 if문이 증가해서 유지보수가 어려운 코드가 된다. 현재는 level이 3개 밖에 없지만, 기능이 추가되어 level이 7개 정도로 늘어난다면 각 level마다 if-else if문을 7개씩 코딩해야 하기 때문이다.
클래스 설계하기
우선 클래스를 좀 더 체계적으로 설계하기 위해 각 플레이어가 가질 수 있는 레벨을 클래스로 분리한다. 각 레벨마다 고통 기능과 개별 기능이 있으므로 레벨 클래스를 상속 관계로 표현할 수 있다.
위 클래스 다이어그램에 포함된 클래스는 모두 하나의 gameLevel 패키지에 만들어야 프로그래밍 제대로 실행된다. Player 클래스와 PlayerLevel 클래스는 포함(HAS-A)관계이다. 게임에서 모든 Player는 자신의 레벨이 있기 때문에, Player 클래스에서 PlayerLevel을 멤버 변수로 갖는 것이다. 레벨이 올라갈 수록 수행하 수 있는 기능이 달라진다. 그러므로 PlayerLevel클래스를 추상 클래스로 만들어 모든 레벨에서 공통으로 수행하는 기능을 구현하고, 각 레벨마다 달라지는 기능은 추상 메서드로 만들어 둔다. 그리고 PlayerLevel을 상속 받는 각 레벨에 해당하는 구현 클래스에서 추상메서드로 선언한 부분을 나름 필요에 맞게 구체적으로 구현한다.
Player 클래스 구현
package gameLevel; public class Player{ //Player가 가지는 level 변수 선언 private PlayerLevel level; //디폴트 생성자. 처음 생성되면 BeginnerLevel로 //시작하며 레벨 메시지 출력 public Player(){ level = new BeginnerLevel(); level.showLevelMessage(); } public PlayerLevel getLevel(){ return level; } //매개변수 자료형은 모든 레벨로 변환 가능한 //PlayerLevel //레벨 변경 메서드 현재 자신의 level을 //매개변수로 받은 level로 변경하고 //레벨 메시지 출력 public void upgradeLevel(PlayerLevel level){ this.level = level; level.showLevelMessage(); } public void play(int count){ //레벨마다 할수 있는 play가 다르므로 //PlayerLevel의 템플릿 메서드 go()호출 level.go(count); } }
Player는 한 번에 하나의 레벨 상태만 가질 수 있으므로 Player를 처음 만들때 가질수 있는 레벨에 해당하는 인스턴스를 대입한다. 그리고 추후에 레벨을 변경할 수 있는 upgradeLevel()메서드도 만든다.
upgradeLevel()메서드를 보자. 실제로 게임에서는 특정 조건을 만족해야 레벨이 올라가겠지만 이 예제에서는 매개변수로 넘어온 레벨로 바로 업그레이드된다.
play()메서드에서는 player가 level에 따라 할 수 있는 행동이 결정 되므로 PlayerLevel 클래스가 제공하는 go()메서드를 호출한다.
PlayerLevel클래스
package gameLevel; public abstract class PalyerLevel{ 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(); } }
초보자 레벨 클래스
package gameLevel; public class BeginnerLevel 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 gameLevel; public class BeginnerLevel 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 gameLevel; public class BeginnerLevel extends PlayerLevel{ @Override public void run(){ System.out.println("엄청 빨리 달린다."); } @Override public void jump(){ System.out.println("아주 높이 Jump 한다."); } @Override public void turn(){ System.out.println("한 바퀴 돕니다."); } @Override public void showLevelMessage(){ System.out.println("*****고급자 레벨입니다.*****"); } }
테스트 프로그램 작성해서 실행하기
package gameLevel; public class MainBoard{ public static void main(String[] args){ //처음 생성하면 BeginnerLevel Player player = new Player(); //*****초보자 레벨입니다.***** player.play(1); //천천히 달린다. //아직 Jump할 수 없습니다. //아직 Turn할 수 없습니다. AdvancedLevel aLevel = new AdvancedLevel(); player.upgradeLevel(aLevel); //*****중급자 레벨입니다.***** player.play(2) //빨리 달린다. //높이 점프한다. //높이 점프한다. //아직 Turn할 수 없습니다. SuperLevel sLevel = new SuperLevel(); player.upgradeLevel(sLevel); //*****고급자 레벨입니다.***** player.play(3); //빨리 달린다. //높이 점프한다. //높이 점프한다. //높이 점프한다. //한 바퀴 돕니다. } }
추상 클래스와 다형성
앞서 만든 Player 클래스와 PlayerLevel 클래스를 살펴보자. 모든 레벨 클래스는 PlayerLevel 클래스를 상속 받았다. 그리고 Player가 가질 수 있는 여러 레벨을 별도의 자료형으로 선언하지 않고 PlayerLevel로 선언했다. 레벨을 변경하는 upgradeLevel()메서드의 매개변수 자료형도 PlayerLevel이다. 따라서 레벨 클래스가 여러 개 존재하더라도 모든 클래스는 PlayerLevel 클래스로 대입될 수 있다. level.go()메서드가 호출되면 가상 메서드에 의해 각 레벨 클래스에 구현된 레벨별 기능이 호출된다. 정리하자면, 상위 클래스인 추상클래스는 하위에 구현된 여러 클래스를 하나의 자료형(상위 클래스 자료형)으로 선언하거나 대입할 수 있다. 추상 클래스에 선언된 메서드를 호출하면 가상 메서드에 의해 각 클래스에 구현된 기능이 호출된다. 즉 하나의 코드가 다양한 자료형을 대상으로 동작하는 다형성을 활용할 수 있는 것이다.
[출저 - Do it! 자바 프로그래밍 입문 , 박은종]
http://www.easyspub.co.kr/20_Menu/BookView/A001/267/PUB
'개발언어 > JAVA' 카테고리의 다른 글
Java - 기본 클래스(Object 클래스, Object의 toStirng()메서드)1 (1) 2023.11.04 Java - 인터페이스(인터페이스와 다형성)2 (0) 2023.11.04 Java - 추상 클래스(템플릿 메서드)3 (0) 2023.11.03 Java - 추상 클래스(추상 클래스 만드는 이유)3 (1) 2023.11.03 Java - 추상 클래스(추상 클래스)1-1 (0) 2023.11.03