싱글톤 패턴처엄 디자인 패턴인 펨플릿 메서드에 대해서 알아보자!!
final메서드와 abstract 메서드로 로직의 흐름만을 정의하고 구체적인 구현은 하위 클래스에 위임한다.
하위 클래스 마다 세부 구현내용은 달라져도 로직의 흐름은 달라지지 않는다.
여러 클래스에서 변하지않는 로직을 템플릿화하여 상위클래스에서 정의하고, 하위 클래스마다 세부 동작 사항을 다르게 구현하는 패턴이다.
final
메소드로 템플릿 메소드를 만들 수 있고, 자식 클래스에서 오버라이딩이 아예 불가능하다.
템플릿 메소드의 흐름을 바꿀 수 없다.
자동차의 로직은 시동켜기 → 운전하기 → 시동끄기로 고정되어 있다.
위의 로직을 final
예약어를 이용해 로직의 흐름을 정의하고, 운전하기부분은 추상메소드를 통해 하위클래스에서 구현하도록 하자
✍️ 예제코드
abstract class Car{
//final 예약어로 로직 고정
public final void carplay(){
turnon();
drive();
turnoff();
}
//일반메소드: 클래스가 동일하게 작동함.
public void turnon(){
System.out.println("시작");
}
public void turnoff(){
System.out.println("시동 끔");
}
//추상 메서드 : 하위클래스에서 각각 다르게 구현함.
public abstract void drive();
}
class ElectricCar extends Car{
//추상메소드 하위클래스에서 구현
@Override
public void drive() {
System.out.println("전기차 드라이브: 매연안나왕");
}
}
class GasolineCar extends Car{
//추상메소드 하위클래스에서 구현
@Override
public void drive() {
System.out.println("휘발유차 드라이브");
}
}
//main 함수
public class CarTest {
public static void main(String[] args) {
Car electricCar = new ElectricCar();
Car regularCar = new GasolineCar();
System.out.println("=============");
regularCar.carplay();
System.out.println("=============");
electricCar.carplay();
System.out.println("=============");
}
}
👉 실행화면
=============
시작
휘발유차 드라이브
시동 끔
=============
시작
전기차 드라이브: 매연안나왕
시동 끔
=============
검색해보니까 방법이 두 개 나온다. 어떤 것이 더 좋을지는 모르겠다...?
final메소드 안에 if문으로 실행 유무를 결정한다.
if문의 조건문을 하위클래스에서 오버라이징할 수 있다.
✍️ 예시코드
package JAVAstudy2023;
abstract class Car{
public final void carplay(){
turnon();
if(hook()){ // 안의 로직을 실행하거나 실행하지 않음
System.out.println("매연 나와요~!");
}
drive();
turnoff();
}
public void turnon(){
System.out.println("시작");
}
public abstract void drive();
public void turnoff(){
System.out.println("시동 끔");
}
//하위 클래스에서 오버라이딩 할 수 있음.
public boolean hook(){
return true;
}
}
class ElectricCar extends Car{
@Override
public void drive() {
System.out.println("전기차 드라이브: 매연안나왕");
}
//false을 반환하여 실행하지 않도록한다.
@Override
public boolean hook() {
return false;
}
}
class GasolineCar extends Car{
@Override
public void drive() {
System.out.println("휘발유 차 드라이브");
}
//따로 hook을 오버라이딩하지 않아 실행
}
public class CarTest {
public static void main(String[] args) {
Car electricCar = new ElectricCar();
Car regularCar = new GasolineCar();
System.out.println("=============");
regularCar.carplay();
System.out.println("=============");
electricCar.carplay();
System.out.println("=============");
}
}
👉 실행화면
=============
시작
매연 나와요~!
휘발유 차 드라이브
시동 끔
=============
시작
전기차 드라이브: 매연안나왕
시동 끔
=============
이번에는 아예 해당 메소드를 하위 메소드에서 빈 구문으로 오버라이딩하는 방법이다.
✍️ 예시코드
package JAVAstudy2023;
abstract class Car{
public final void carplay(){
turnon();
sootGeneration();
drive();
turnoff();
}
public void turnon(){
System.out.println("시작");
}
public void sootGeneration(){
System.out.println("매연 나와요~");
}
public abstract void drive();
public void turnoff(){
System.out.println("시동 끔");
}
}
class ElectricCar extends Car{
@Override
public void drive() {
System.out.println("전기차 드라이브: 매연안나왕");
}
@Override
public void sootGeneration(){ //오버라이딩을 통해서 아예 실행을 안하도록!!
}
}
class GasolineCar extends Car{
@Override
public void drive() {
System.out.println("휘발유 차 드라이브");
}
}
public class CarTest {
public static void main(String[] args) {
Car electricCar = new ElectricCar();
Car regularCar = new GasolineCar();
System.out.println("=============");
regularCar.carplay();
System.out.println("=============");
electricCar.carplay();
System.out.println("=============");
}
}
👉 실행화면
=============
시작
매연 나와요~
휘발유 차 드라이브
시동 끔
=============
시작
전기차 드라이브: 매연안나왕
시동 끔
=============
예약어 | 메소드 | 특징 |
---|---|---|
non | 일반메소드 | 하위클래스에서 오버라이딩 가능 |
abstract | 추상메소드 | 하위클래스에서 오버라이딩 필수 |
final | 템플릿메소드 | 하위클래스에서 오버라이딩 불가능 |
템플릿메소드는 로직을 고정하는데 유용하며 final예약어를 사용한다.