FireDrago

[객체지향과 디자인패턴] 전략패턴 본문

프로그래밍/디자인패턴

[객체지향과 디자인패턴] 전략패턴

화이용 2024. 9. 6. 14:36

디자인 패턴

객체지향 설계 원칙을 적용하여 설계를 하다보면 비슷한 상황에서 사용하는 일정한 패턴들이 있다.

이를 디자인패턴이라고 한다.  디자인 패턴을 집대성한 GoF(Gang of Four)가 대표적이다.

 

1. 코드 재사용성 향상: 디자인 패턴을 사용하면 검증된 설계 방식을 반복사용할 수 있어 코드의 재사용성을 높인다

2. 유지보수성 개선: 코드의 구조가 명확해져서 유지보수가 쉬워지고, 변경이 발생하더라도 영향 범위를 줄일 수 있다.

3. 객체지향 설계 원칙 준수: SOLID 원칙 등 객체지향 설계의 기본 원칙을 패턴을 통해 자연스럽게 적용할 수 있다.

 

전략패턴 (Strategy Pattern)

전략 패턴은 객체의 행위를 캡슐화하여, 알고리즘을 클래스화하고, 동적으로 변경할 수 있게 만드는 디자인 패턴

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;
        }
    }
}

위 코드는 첫손님과 신선하지 않은 제품에 할인을 적용하고 이를 계산하는 Calculator 클래스이다.
서로 다른 계산 정책들이 한 코드에 섞여 있어, 정책이 추가될수록 코드 분석을 어렵게 만든다.
할인정책이 추가될 때마다 calculate 메서드를 수정하는 것이 점점 어려워진다.

public class Calculator {
    // 할인 전략을 인터페이스로분리
    private DiscountStrategy discountStrategy;
    
    // 할인 클래스 구현체를 외부에서 주입
    public Calculator (DiscountStrategy discountStrategy) {
        this.discountStrategy = discountStrategy;
    }
    
    public int calculate(List<Item> items) {
        int sum = 0;
        for (Item item : items) {
            sum += discountStrategy.getDiscountPrice(item);
        }
        return sum;
    }
}
// Calculator에서 사용하는 전략 인터페이스
public interface DiscountStrategy {
    int getDiscountPrice(item item);
}

// DiscountStrategy 인터페이스를 구현한 콘크리트 클래스
public class FirstguestDiscountStrategy implements DiscountStrategy {
    @Override
    public int getDiscountPrice(Item item) {
        return (int)(item.getPrice() * 0.9);
    }
}

위의 코드는 전략 패턴을 적용하여 Calculator 클래스의 할인 계산 로직을 캡슐화하고,

서로 다른 할인 정책들을 독립적으로 관리할 수 있게 만들었다.

새로운 할인 정책을 쉽게 추가하고 기존의 코드를 수정하지 않고도 전략을 변경할 수 있다.

 

전략패턴의 장점

1.  콘텍스트 코드의 변경 없이 새로운 전략을 추가할 수 있다.
     예제에서 마지막 손님 할인 정책을 추가하는 경우, Calculator는 변경되지 않는다.

2.  개방 폐쇄 원칙을 따르는 구조를 갖게 된다. 확장에는 열려있고 변경에는 닫혀 있게 된다.

3.  if-else로 구성된 코드 블록이 비슷한 기능을 수행하는 경우 전략패턴 적용을 고민해보자