본문 바로가기

백엔드 지식 저장소

전략 패턴이란?

728x90

전략패턴

전략 패턴은 실행 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴입니다. 어떤 일을 수행하는 알고리즘이 여러 가지 일 때, 동작들을 미리 전략으로 정의함으로써 손쉽게 전략을 교체할 수 있는, 알고리즘 변형이 빈번하게 필요한 경우에 적합합니다..

 

전략 패턴 구조

전략패턴 구조

코드로 바로 어떤 구조인지 확인하러 가시죠

public interface Strategy {
	void call();
}

---------------------------------------------------

@Slf4j
public class StrategyLogicV1 implements Strategy{
	@Override
	public void call() {
		log.info("비즈니스 로직1 실행");
	}
}

---------------------------------------------------

@Slf4j
public class StrategyLogicV2 implements Strategy{
	@Override
	public void call() {
		log.info("비즈니스 로직2 실행");
	}
}

Strategy 인터페이스는 변하는 알고리즘을 의미합니다. StrategyLogic1과 StrategyLogic2는 Strategy인터페이스를 구현한 클래스입니다.

 

다음은 Context클래스입니다. 이 클래스는 변하지 않는 알고리즘을 갖고 있는 템플릿 역할을 합니다.

@Slf4j
public class ContextV2 {

	public void execute(Strategy strategy) {
		long startTime = System.currentTimeMillis();
		//비즈니스 로직 실행
		strategy.call(); //위임
		//비즈니스 로직 종료
		long endTime = System.currentTimeMillis();
		long resultTime = endTime - startTime;
		log.info("resultTime = {}", resultTime);
	}
}

전략을 필드로 가지지 않습니다. 대신에 전략을 execute(..) 가 호출될 때마다 항상 파라미터로 전달받습니다.

 

테스트 클래스를 작성하여 어떤 결과를 보여주는지 확인했습니다.

@Slf4j
public class ContextV2Test {

	/**
	 * 전략 패턴 적용
	 */
	@Test
	void strategyV1() {
		ContextV2 context = new ContextV2();
		context.execute(new StrategyLogicV1());
		context.execute(new StrategyLogicV2());

	}

단순 전략 패턴 적용 코드 결과값

전략 패턴 파라미터 실행을 그림으로 표현하면

전략 패턴 파라미터

1. 클라이언트가 Context를 실행하면서 Strategy를 인수로 전달합니다.

2. excute 로직을 실행합니다.

3. strategy.call로직을 수행합니다.

4. excute로직이 종료됩니다.

 

하지만 단지 전략패턴만 적용하였을 때 StrategyLogicV1과 StrategyLogicV2가 코드상에 나타나 있습니다. 이를 익명 내부 클래스로 전환할 수 있습니다.

 

/**
* 전략 패턴 익명 내부 클래스
*/
	@Test
	void strategyV2() {
		ContextV2 context = new ContextV2();
		context.execute(new Strategy() {
			@Override
			public void call() {
				log.info("비즈니스 로직1 실행");
			}
		});
		context.execute(new Strategy() {
			@Override
			public void call() {
				log.info("비즈니스 로직2 실행");
			}
		});

	}

 

Strategy 인터페이스에 메서드가 하나만 있어서 이를 람다로도 바꿀 수 있다. 인텔리제이를 사용하면 정말 변환이 쉽게 변경 가능합니다.

 

/**
* 전략 패턴 익명 내부 클래스2, 람다
*/
	@Test
	void strategyV3() {
		ContextV2 context = new ContextV2();
		context.execute(() -> log.info("비즈니스 로직1 실행"));
		context.execute(() -> log.info("비즈니스 로직2 실행"));

	}

확실히 간략해진 코드를 확인할 수 있습니다. 하지만 람다를 사용하여 구현을 할 경우 interface에 메서드가 하나만 있어야 하는 주의 사항이 있습니다!!

 

전략패턴을 좀 더 이해할 수 있었던 시간이었던 같습니다. 감사합니다!!

 

김영한 님의 스프링 핵심 원리 - 고급편을 기반으로 작성한 포스팅입니다. 문제 발생 시 삭제하겠습니다!

728x90