공부하며 작성한 포스트입니다. 틀린 내용이나 부실한 설명이 있다면 알려주세요.😁
전략 패턴 또는 정책 패턴은 실행 중에 알고리즘을 선택할 수 있게 하는 행위 소프트웨어 디자인 패턴이다. 전략 패턴은 특정한 계열의 알고리즘들을 정의하고 각 알고리즘을 캡슐화하며 이 알고리즘들을 해당 계열 안에서 상호 교체가 가능하게 만든다. - 위키백과
전략 패턴은 프로그램 또는 소스코드 진행 중에 알고리즘을 선택할 수 있게 하기 위한 디자인 패턴입니다. 전략 패턴을 적용하면, 사전에 정의하고 캡슐화 한 알고리즘을 개발자가 원하는 영역 안에서 교체 및 선택할수 있습니다. 한마디로, 특정 영역 안에서 알고리즘을 선택하여 적용할 수 있게 하는 설계 방법입니다.
한 건물안에 자판기가 있습니다. 이 자판기는 버튼을 누르면 해당 버튼에 알맞는 음료를 뽑아줍니다.
public class DrinkMachine{
public DrinkMachine(String button){
String drink;
if(button == "탄산"){
drink = "탄산음료";
}else if(button == "이온음료"){
drink = "이온음료";
}else{
drink = "물";
}
return drink;
}
}
위의 코드에서 알 수 있듯, 전략 패턴을 사용하지 않는다면 if-else
블럭으로 코드를 제어해야 합니다. 이는 코드의 유연성을 떨어뜨리고 하나의 메소드에 너무 많은 로직을 추가해야 합니다. 여기서 자판기의 음료가 추가되어 커피, 과일주스가 추가된다고 가정 해 봅시다.
그렇다면 위의 코드에서 커피, 과일주스에 대한 if-else
코드블럭이 추가로 작성되어야 할 것이고, 이처럼 간단한 코드가 아닌 100줄, 1000줄 짜리 복잡한 로직이라면 Copy-Paste가 거의 불가능할것입니다.
다음과 같이 음료 종류를 인터페이스화 하고 이를 구현해보겠습니다.
public interface Beverage{
void vend();
}
public class Soda implements Beverage{
private final String DRNIK = "탄산음료";
@override
public void vend(){
return DRINK;
}
}
public class Coffee implements Beverage{
private final String DRINK = "커피";
@override
public void vend(){
return DRINK;
}
위와 같이 음료를 하나의 클래스로 만들고, 이 클래스들을 자판기에 붙이도록 하겠습니다.
public class VendingMachine{
public String vend(Beverage beverage){
return beverage.vend();
}
}
public class Building{
public static void main(String[] args){
VendingMachine vendingMachine = new VendingMachine();
// 자판기 설치.
String soda = vendingMachine.vend(sodaButton());
// soda 버튼을 누르면 탄산음료 추출.
String coffee = vendingMachine.vend(coffeeButton());
// coffee 버튼을 누르면 커피 추출.
}
public static Beverage sodaButton(){
return new Soda();
}
public static Beverage coffeeButton(){
return new Coffee();
}
}
이제 자판기에 추가하고자 하는 메뉴 혹은 교체하고자 하는 메뉴가 있다면, 음료를 만들고(알고리즘 정의)하고 누르는 버튼(전략)만 다르게 주면 됩니다. 이처럼 각각의 영역에 다른 전략을 취하는 방법을 전략 패턴이라 합니다.
코드 수정이 발생했을 때
전략패턴을 적용하지 않았을 때 >>if-else
블럭 추가
전략패턴 적용 시 >>Class
추가
전략 패턴의 장점
첫 번째는 기존 메소드의 직접적인 수정 없이 새로운 알고리즘을 추가할 수 있다는 것입니다.(OCP원칙)
두 번째는 유지보수에 장점이 있습니다. 위 코드에서 새로운 메뉴를 추가하고 기존에 있던 메뉴를 변경하게 된다해도 기존에 있던 코드는 변함이 없습니다. 하지만 전략패턴을 사용하지 않은 코드에서는 기존에 있던 코드를 수정해야겠죠?
예시를 든 코드는 아주 간단해서 사실 전략패턴이 필요 없지만, 만약 실제 프로젝트에서 1000줄짜리, 2000줄짜리 코드의 분기가 일어난다면 유지보수에 있어서 리스크가 더 클수밖에 없습니다.
장점만 있는 기술은 존재하지 않습니다.
알고리즘이 다수 있는 프로그램은 전략패턴보다 일반적인 if-else
구문이 보기에 더 편하고 깔끔할 수 있습니다. 즉, 모든 상황에서 사용되는 만능 코드는 아니라는 것입니다. 극단적인 예를들어, 알고리즘의 변화가 없고 사용하는 영역이 하나라면 굳이 전략패턴을 사용할 필요 없이 바로 적용하면 되겠죠? 단순한 프로그램에 적용할수록, 오히려 코드의 복잡도는 더 올라갈 수 있습니다.
전략 패턴은 클라이언트의 요구사항 변경 및 다양한 영역에서의 여러가지 알고리즘을 적용할 때 사용하면 빛을 발하는 패턴입니다. 모든 상황에서 통용되는 만능 기법은 물론 아니며, 상황에 따라 어떤 패턴을 사용하고 무슨 기법을 적용할지는 오롯이 개발자의 몫으로 돌아가며, 그 선택에 따른 책임과 결과물도 개발자의 몫이라고 생각합니다.