주난v 개발 성장기

[디자인 패턴] 전략(Strategy) 패턴 본문

개발 성장기/디자인 패턴

[디자인 패턴] 전략(Strategy) 패턴

주난v 2020. 7. 7. 08:07

전략 패턴

- 객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성

- 유사한 행위들을 캡슐화하는 인터페이스 생성

- 객체의 행위를 직접 수정하지 않고, 런타임 시점에 전략을 바꿔주어서 행위를 유연하게 확장

 

기능 위임.

 

기존 코드의 변경 없이 외부 주입만 변경하면서 사용하는 패턴

 

as-is 

- 계산 클래스에서 모든 처리를 다해줌

- 조건이 추가된다면 코드가 무한정 증가되는 단점을 가짐

public class Calculator {
	
    public int calculate(boolean firstGuest, List<Item> items) {
    	int sum = 0;
        for (Item item : items) {
        
        	if (firstGuest) {
            	sum += (int) (item.getPrice() * 0.9);// 첫 손님 10% 할인
            } else if (!item.isFresh()) {
            	sum += (int) (item.getPrice() * 0.8);// 덜 신선한 것 20% 할인
            } else {
            	sum += item.getPrice();
            }
        }
        return sum;
    }
}

 

to-be

공통 행위를 인터페이스로 캡슐화하고, 각각의 전략은 클래스로 분리하여 유연하게, 확장성 있게 만든다.

//콘텍스트
public class Calculator {
	public int calculate(List<Item> items);
}

//전략

//캡슐화를 위한 인터페이스
public interface DiscountStrategy {
	int getDiscountPrice(Item item);
}

//전략 콘크리트 클래스
public class FirstGuestDiscountStrategy implements DiscountStrategy {
	public int getDiscountPrice(Item item) {
    	...
    }
}

public class NonFreshItemDiscountStrategy implements DiscountStrategy {
	public int getDiscountPrice(Item item) {
    	...
    }
}

 

전략 패턴에서 콘텍스트는 사용할 전략을 직접 선택하지 않는다.

DI를 이용해서 콘텍스트에 전략을 전달해 준다.

 

전략 패턴의 장점

- 콘텍스트 코드의 변경 없이 새로운 전략을 추가할 수 있다.

- 전략 추가로 인해 기존 코드가 변경된다면 문제가 발생한다.(기능 결함, QA 필요 등)

 

전략 패턴을 이용함으로써,

Calculator 클래스는 할인 정책 확장에는 열려 있고, 변경에는 닫혀 있는 OCP 원칙을 따른다.

 

* 참고

 

자바 8에서도 Predicate를 이용하여 동작 파라미터화를 구현할 수 있는데, 이때 전략 패턴을 이용하여 런타임 시에 알고리즘을 변경하고

원하는 다양한 결과를 얻을 수 있다.