Burninghering's Blog
article thumbnail

추상 클래스의 응용 - 템플릿 메서드 패턴

라이브러리는 가져다쓸 수 있는 여러가지 함수들 모음

프레임워크는

JDK(Java Development Kit 자바의 좋은 라이브러리)에서 많이 가져다 쓰지만,

전체적인 프로그램의 제어권은 프로그램이 가지고 있는 것이다.

 

안드로이드 같은 프레임워크는 

이미 흐름이 다 정해져있고,

(클래스를 넣으면 어떻게 연동이 되고, 저 클래스를 넣으면 메시지가 날아가고 어떤 영향을 준다.. 등)

(화면이(액티비티) 생성과정, 소멸과정, 안에서 돌아가는 일들은 다 정해져있다)

 

우리같은 프로그래머가 하는 일들은 구멍을 메꾸는 일이다.

(화면에서 위젯이 올라온다 등..)

 

템플릿 메서드는 프레임워크에서 많이 쓰는 패턴이다.

이미 시나리오가 다 정해져 있고, 

메세지나 클래스를 만드는 것은 우리가 해야하는 일이다.

 

그러므로 프레임워크를 도입하려면 내가 어떻게 해야 어떻게 시스템이 돌아가는지 공부를 해야한다.

1. 템플릿 메서드(틀, 정해진 흐름을 가진 메서드)

시나리오를 정해놓고, 그에 따라 흘러가는데 그 안에 추상 메서드들이 있다

그 추상 메서드들을 상속받은 클래스 측에서 구현을 한다.

  • 추상 메서드나 구현된 메서드를 활용하여 코드의 흐름(시나리오)를 정의하는 메서드
  • final로 선언하여 하위 클래스에서 재정의 할 수 없게 함(흐름이 변하면 안되므로)
  • 클래스에 final이 들어가면 상속받을 수 없음(하위 클래스에서 값을 바꾸면 안되므로)
  • 프레임워크에서 많이 사용되는 설계 패턴
  • 추상 클래스로 선언된 상위 클래스에서 템플릿 메서드를 활용하여 전체적인 흐름을 정의하고, 하위 클래스에서 다르게 구현되어야 하는 부분은 추상 메서드로 선언하여 하위 클래스에서 구현 하도록 함

final이

변수에 쓰이면 상수

메서드에 쓰이면 재정의를 못하는 메서드

클래스에 쓰이면 상속을 못하는 메서드

 

2. 템플릿 메서드 예제

Car.java

package ch10;

public abstract class Car {
	public abstract void drive();
	public abstract void stop();
	
	public void startCar() {
		System.out.println("시동을 켭니다.");
	}
	public void turnOff() {
		System.out.println("시동을 끕니다.");
	}
	
	final public void run() { //추상메서드가 있건 없건, 시나리오를 세운다(변하면 절대 안됨)
		startCar();
		drive();
		stop();
		turnOff();
	}
}

 

AICar.java

package ch10;

public class AICar extends Car{

	@Override
	public void drive() {
		System.out.println("자율 주행을 합니다.");
		System.out.println("자동차가 스스로 방향을 바꿉니다.");
	}

	@Override
	public void stop() {
		System.out.println("장애물 앞에서 스스로 멈춥니다.");
	}
}

 

ManualCar.java

package ch10;

public class ManualCar extends Car {

	@Override
	public void drive() {
		System.out.println("사람이 운전합니다.");
		System.out.println("사람이 핸들을 조작합니다.");
	}

	@Override
	public void stop() {
		System.out.println("장애물 앞에서 브레이크를 밟아서 정지합니다.");
	}
}

 

CarTest.java

package ch10;

public class CarTest {

	public static void main(String[] args) {
		Car aiCar = new AICar();
		aiCar.run();
		
		Car mCar = new ManualCar();
		mCar.run();
	}
}

 

결과!

 

 

Car 상위 클래스의 run()과 같은 시나리오가 있으면 우리가 변경할 수 없고,

abstract 메서드들은 하위 클래스에서 필요에 의해 변경해서 쓸 수 있다.

 

새로운 기능을  추가해 시나리오에 넣으면, 하위 클래스들에서 에러가 난다.

 

구현된 메서드를 시나리오에 넣으면 에러가 나지 않는다 

 

 

AICar.java

	@Override
	public void washCar() {
		System.out.println("자동 세차를 합니다.");

 

CarTest.java

package ch10;

public class CarTest {

	public static void main(String[] args) {
		Car aiCar = new AICar();
		aiCar.run();
		
		System.out.println("===================");
		
		Car mCar = new ManualCar();
		mCar.run();
	}
}

 

결과

washCar() 메서드를 AICar에서는 재정의를 했고, ManualCar에서는 재정의를 하지 않았다.

필요한 경우에, 상위 메서드에서 정의해놓은 메서드를 가져다 쓰는 "쿡 메서드"

 

 

3. final 예약어

  • final 변수 : 값이 변경될 수 없는 상수

   public static final double PI = 3.14;

  • final 메서드 : 하위 클래스에서 재정의 할 수 없는 메서드
  • final 클래스 : 상속할 수 없는 클래스

 

4. 여러 자바 파일에서 사용하는 상수 값 정의

Define.java

public static final로 정수/상수/스트링들을 한 곳에 모아놓으면

public class Define {

	public static final int MIN = 1;
	public static final int MAX = 999999;
	public static final double PI = 3.14;
	public static final String GREETING = "Good Morning!";
	public static final int MATH_CODE = 1001;
	public static final int CHEMISTRY_CODE = 1002;
	
}

UsingDefine.java

프로그램 안에서 공통으로 쓰여야 하는 값들을 new 하지 않고 Define. 해서 사용할 수 있다

public class UsingDefine {

	public static void main(String[] args) {

		System.out.println(Define.GREETING);
		System.out.println(Define.MIN);
		System.out.println(Define.MAX);
		System.out.println(Define.MATH_CODE);
		System.out.println(Define.CHEMISTRY_CODE);
		System.out.println("원주률은" + Define.PI + "입니다.");
	}

}
profile

Burninghering's Blog

@개발자 김혜린

안녕하세요! 반갑습니다.