추상 메서드란 메서드의 선언만 있고 구현이 없는 메서드를 말한다.
즉, 구체적인 동작이 정의되지 않은 메서드로, 반드시 추상 클래스(abstract class) 또는 인터페이스(interface)에서만 선언할 수 있다.
그리고 하나 이상의 추상 메소드를 포함하는 클래스를 가리켜 추상 클래스(abstract class)라고 한다.
간단한 예제를 통해서 알아보자.
추상 메서드 추상 클래스를 이용하지 않았을때
@Slf4j
public class TemplateMethodTest {
@Test
void templateMethodV0(){
logic1();
logic2();
}
private void logic1(){
long startTime = System.currentTimeMillis();
//비즈니스 로직 실행
log.info("비즈니스 로직1 실행");
//비즈니스 로직 종료
long endTime = System.currentTimeMillis();
long result = endTime - startTime;
log.info("resultTime={}",result);
}
private void logic2(){
long startTime = System.currentTimeMillis();
//비즈니스 로직 실행
log.info("비즈니스 로직2 실행");
//비즈니스 로직 종료
long endTime = System.currentTimeMillis();
long result = endTime - startTime;
log.info("resultTime={}",result);
}
}
위 코드를 보면 logic1과 logic2가 log에 대한 정보만 다르고 모두 반복되는 코드라는 것을 확인할 수 있다.
이때, 반복되는 코드로 인해 코드에 대한 가독성이 떨어져서 이해도가 떨어질 수 있다.
이러한 상황에 추상 클래스와 추상 메서드를 사용하면 반복되는 코드를 줄일 수 있다.
추상 메서드, 추상 클래스 사용했을때
<추상 클래스 AbstractTemplate>
@Slf4j
public abstract class AbstractTemplate {
/**
* 템플릿 메서드 패턴을 적용한 실행 메서드.
* 실행 시간을 측정하면서 비즈니스 로직(call 메서드)을 실행함.
*/
public void execute(){
long startTime = System.currentTimeMillis();
// 비즈니스 로직 실행 (하위 클래스에서 구현)
call();
// 실행 종료 시간 기록
long endTime = System.currentTimeMillis();
long result = endTime - startTime; // 총 실행 시간 계산
// 실행 시간 로깅
log.info("resultTime={}", result);
}
/**
* 추상 메서드: 실제 비즈니스 로직은 하위 클래스에서 구현해야 함.
*/
protected abstract void call();
}
로그에 대한 정보는 추상 메서드인 call() 메서드로 빼줘서 logic1과 logic2를 다르게 구현해야한다.
<logic1에 대한 추상 클래스 SubClassLogic1>
@Slf4j
public class SubClassLogic1 extends AbstractTemplate{
@Override
protected void call() {
log.info("비즈니스 로직1 실행");
}
}
추상 클래스를 상속받아서 추상 메서드를 오버라이드 해줌으로써 추상 메서드 구현이 가능해진다.
<logic2에 대한 추상클래스 SubClasslogic2>
@Slf4j
public class SubClassLogic2 extends AbstractTemplate{
@Override
protected void call() {
log.info("비즈니스 로직2 실행");
}
}
템플릿 메서드 페턴을 적용했기 때문에 AbstractTemplate 클래스를 상속받은 SubClassLogic1과 SubClassLogic2 가 각각 call()메서드를 다르게 구현하여 반복되는 코드를 줄이고 유지보수 또한 쉬워지게 된다!
@Slf4j
public class TemplateMethodTest {
@Test
void templateMethodV1(){
AbstractTemplate template1 = new SubClassLogic1();
template1.execute();
AbstractTemplate template2 = new SubClassLogic2();
template2.execute();
}
}
익명 내부 클래스( Anonymous Inner Class )
위 예시와 같이 별도의 클래스를 선언하여 추상 메서드를 오버라이드 하는 방법도 있지만,
익명 내부 클래스를 사용하여 추상 메서드를 즉석에서 구현하는 방법도 있다.
@Test
void templateMethodV2(){
AbstractTemplate template1 = new AbstractTemplate() {
@Override
protected void call() {
log.info("비즈니스 로직1 실행");
}
};
log.info("클래스 이름1={}",template1.getClass());
template1.execute();
AbstractTemplate template2 = new AbstractTemplate() {
@Override
protected void call() {
log.info("비즈니스 로직2 실행");
}
};
log.info("클래스 이름2={}",template2.getClass());
template2.execute();
}
익명 내부 클래스는 재사용이 필요없는 일회성 클래스에서 사용하는 것이 가독성과 유지보수 측면에서 유리하고,
반복적으로 사용할 경우 별도의 클래스를 만들어서 상속해주는 것이 좋다.
'자바' 카테고리의 다른 글
동시성 문제를 해결하기 위한 ThreadLocal[java] (0) | 2025.03.05 |
---|---|
Thread란 무엇인가[Java] (1) | 2025.03.02 |
예외 (0) | 2025.02.02 |
HashMap (0) | 2024.02.21 |
Iterator (2) | 2024.02.21 |