-
전략 패턴 (Strategy Pattern)디자인 패턴 2022. 8. 13. 15:13
전략 패턴
여러 알고리즘들을 캡슐화하고 상호 교환 가능하게 만드는 패턴
- 컨텍스트에서 사용할 알고리즘들을 클라이언트에서 선택한다.
즉, 특정 업무를 수행하는 방법이 여러가지 일 경우 여러가지 방법들을 각각의 클래스로 캡슐화하면 캡슐화된 것을 공통 인터페이스로 추상화하여 업무를 수행하는 Client 에서는 공통 인터페이스를 사용하게 하여 Client 코드는 변경되지 않고도 여러 방법들을 바꿔 낄 수 있다.
- Context : 원래 로직을 수행하던 클래스
- ConcreteStrategy : 각각의 알고리즘들이 구현된 클래스
- Strategy : 추상화된 알고리즘 수행 인터페이스
전략 패턴 적용 전
"무궁화 꽃이 피었습니다" 를 실행하는 프로그램이 있다.
이 게임은 "무궁화 꽃이" 까지는 파란불이며, "피었습니다." 까지는 빨간불로 구현을 하였고 여기에 Speed 라는 필드를 정의하여 "무궁화 꽃이" 혹은 "피었습니다." 를 말하는 속도를 조절 할 수 있도록 하는 기능을 넣었다.
BlueLightRedLight
public class BlueLightRedLight { private int speed; public BlueLightRedLight(int speed) { this.speed = speed; } public void blueLight() { if (speed == 1) { System.out.println("무 궁 화 꽃 이"); } else if (speed == 2) { System.out.println("무궁화 꽃이"); } else if (speed == 3){ System.out.println("무광꼬치"); } } public void redLight() { if (speed == 1) { System.out.println("피 었 습 니 다."); } else if (speed == 2) { System.out.println("피었습니다."); } else if (speed == 3){ System.out.println("펴씀다"); } } }
문제점
speed 에 따라 분기를 나눠야하고 다르게 행동해야 한다.
또한 다르게 행동하기 위해 Client 에서 Speed 를 1, 2, 3 과 같은 구체적인 숫자를 바꿔줘야하고 새로운 Speed 4 가 생기면 기존 코드를 수정해야 하는 문제가 발생한다.
이를 전략 패턴을 이용하여 해결해보자.
전략 패턴 적용 후
먼저 Strategy 인터페이스를 정의한다.
// Strategy public interface Speed { void blueLight(); void redLight(); }
ConcreteStrategy 를 구현하자.
Slow, Normal, Faster 를 정의하여 이전에 방식의 speed 1, 2, 3 에 해당되는 기능을 구현해준다.
public class Slower implements Speed { @Override public void blueLight() { System.out.println("무 궁 화 꽃 이"); } @Override public void redLight() { System.out.println("피 었 습 니 다."); } }
public class Normal implements Speed { @Override public void blueLight() { System.out.println("무궁화꽃이"); } @Override public void redLight() { System.out.println("피었습니다."); } }
public class Faster implements Speed { @Override public void blueLight() { System.out.println("무광꼬치"); } @Override public void redLight() { System.out.println("펴씀다."); }
Context 인 BlueLightRedLight 는 아래와 같다.
// Context public class BlueLigthRedLight { private Speed speed; public BlueLigthRedLight(Speed speed) { this.speed = speed; } public void blueLight() { speed.blueLight(); } public void redLight() { speed.redLight(); } }
생성자에서 Speed 타입 클래스 (Slower, Normal, Faster) 중 하나를 받아 그에 따르는 로직을 처리한다.
Client 는 아래와 같이 호출 할 수 있다.
public class Client { public static void main(String[] args) { BlueLigthRedLight blueLigthRedLight = new BlueLigthRedLight(new Slower()); blueLigthRedLight.blueLight(); blueLigthRedLight.redLight(); } }
만약, BlueLight 와 RedLight 의 속도를 다르게 하고 싶으면 생성자가 아닌 메소드에서 Speed 타입 클래스를 인자로 받으면 된다.
public class BlueLigthRedLight { public void blueLight(Speed speed) { speed.blueLight(); } public void redLight(Speed speed) { speed.redLight(); } }
public class Client { public static void main(String[] args) { BlueLigthRedLight blueLigthRedLight = new BlueLigthRedLight(); blueLigthRedLight.blueLight(new Slower()); blueLigthRedLight.redLight(new Faster()); } }
장점과 단점
장점
- 새로운 전략을 추가하더라도 기존 코드를 변경하지 않는다. (OCP)
- 상속 대신 위임을 사용할 수 있다.
- 런타임에 전략을 변경할 수 있다.
단점
- 복잡도가 증가한다.
- 클라이언트 코드가 구체적인 전략을 알아야 한다.
실무에선 어떻게 쓰이나?
자바의 Comparator
public class StrategyInJava { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); numbers.add(2); numbers.add(1); numbers.add(3); numbers.add(5); numbers.add(4); Collections.sort(numbers, new Comparator<Integer>() { @Override // ConcreteStrategy public int compare(Integer o1, Integer o2) { return o1 - o2; } }); } }
Spring 의 ApplicationContext 등등
public class StrategyInSpring { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext(); ApplicationContext applicationContext1 = new FileSystemXmlApplicationContext(); ApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(); BeanDefinitionParser parser; CacheManager cacheManager; // 다양한 캐시 전략을 제공 } }
참고
'디자인 패턴' 카테고리의 다른 글
비지터 패턴 (Visitor Pattern) (0) 2022.08.13 템플릿 메서드 패턴 (Template Method Pattern) (0) 2022.08.13 상태 패턴 (State Pattern) (0) 2022.08.13 메멘토 패턴 (Memento Pattern) (0) 2022.08.12 중재자 패턴 (Mediator pattern) (0) 2022.08.11