전략 패턴(Strategy Pattern)

SeungJoo
|2025. 1. 12. 21:34
반응형

전략 패턴이란

전략 패턴은 여러 가지 방법(알고리즘)을 미리 만들어 놓고, 필요할 때 그중 하나를 골라 사용하는 것입니다. 이렇게 하면 필요할 때마다 새로운 방법을 쉽게 추가할 수 있습니다.

전략 패턴을 사용 시 이점

1. 동작의 유연한 변경 : 실행 중에 원하는 전략(행동)을 교체할 수 있습니다.

2. 코드 수정 최소화 : 새로운 전략을 추가해도 기존 코드를 수정하지 않아도 됩니다.

3. 유지보수성 향상 : 코드가 분리되어 있어 가독성과 유지보수가 쉬워집니다.

예시 : 택배 배송 시스템

문제 사항

우리는 택배를 고객에게 배송해야 합니다.

배송 방법은 오토바이, 트럭, 드론 중 하나를 선택할 수 있습니다.

고객의 위치, 물건의 크기, 긴급성에 따라 적절한 배송방법을 선택해야 합니다.

새로운 배송 방법이 추가될 가능성도 있습니다.

배송 방법을 변경할 때마다 기존 코드를 수정해야 한다면, 유지보수에 큰 어려움이 생길 수 있습니다.

 

 

유지보수가 어려운 코드 ( if-else 조건문으로 배송방법을 결정)

public class Delivery {
    public static final int MOTORCYCLE = 1;
    public static final int TRUCK = 2;
    public static final int DRONE = 3;

    private int deliveryMethod;

    void setDeliveryMethod(int method) {
        this.deliveryMethod = method;
    }

    void deliver(String packageDetails) {
        if (deliveryMethod == MOTORCYCLE) {
            System.out.println("오토바이로 " + packageDetails + "를 배송합니다.");
        } else if (deliveryMethod == TRUCK) {
            System.out.println("트럭으로 " + packageDetails + "를 배송합니다.");
        } else if (deliveryMethod == DRONE) {
            System.out.println("드론으로 " + packageDetails + "를 배송합니다.");
        }
    }
}

public class DeliveryMain {
    public static void main(String[] args) {
        Delivery delivery = new Delivery();

        delivery.setDeliveryMethod(Delivery.MOTORCYCLE);
        delivery.deliver("소형 패키지"); // "오토바이로 소형 패키지를 배송합니다."

        delivery.setDeliveryMethod(Delivery.TRUCK);
        delivery.deliver("대형 패키지"); // "트럭으로 대형 패키지를 배송합니다."
    }
}

문제점 분석

1. 조건문 증가 :  배송 방법이 추가될 때마다 if-else 조건문이 늘어납니다. (ex : 새로운 배송 방법을 추가하면 if - else 조건문이 늘어납니다.)

2. 코드 수정 필요 : 기존 코드를 수정해야 하므로 OCP(Open-Close Principle, 개방-폐쇄 원칙)을 위반합니다.

3. 유지 보수 어려움 : 조건문이 많아질수록 가독성이 떨어지고, 버그가 발생할 가능성이 높아집니다.

 

전략 패턴을 적용한 코드

전략 패턴의 해결 방법

각 배송 방법을 별도의 클래스로 분리합니다.

모든 배송 방법은 DeliveryStrategy라는 공통 인터페이스를 구현합니다.

컨텍스트 클래스인 DeliveryContext에서 전략 개체를 동적으로 설정하여 동작을 실행합니다.

 

전략 인터페이스

public interface DeliveryStrategy {
	void deliver(String packageDetails);
}

각 전략 구현체 정의(배송 방법마다 별도의 클래스를 만듭니다.)

public class MotorcycleDelivery implements DeliveryStrategy {
    @Override
    public void deliver(String packageDetails) {
        System.out.println("오토바이로 " + packageDetails + "를 배송합니다.");
    }
}
public class TruckDelivery implements DeliveryStrategy {
    @Override
    public void deliver(String packageDetails) {
        System.out.println("트럭으로 " + packageDetails + "를 배송합니다.");
    }
}
public class DroneDelivery implements DeliveryStrategy {
    @Override
    public void deliver(String packageDetails) {
        System.out.println("드론으로 " + packageDetails + "를 배송합니다.");
    }
}

컨텍스트 클래스 정의

DeliveryContext는 전략 객체를 설정하고 실행하는 역할을 합니다.

public class DeliveryContext {
    private DeliveryStrategy deliveryStrategy;

    // 배송 전략 설정
    public void setDeliveryStrategy(DeliveryStrategy deliveryStrategy) {
        this.deliveryStrategy = deliveryStrategy;
    }

    // 배송 실행
    public void deliverPackage(String packageDetails) {
        if (deliveryStrategy == null) {
            throw new IllegalStateException("배송 전략이 설정되지 않았습니다!");
        }
        deliveryStrategy.deliver(packageDetails);
    }
}

클라이언트 코드 

클라이언트는 전략 객체를 생성하고, 이를 DeliveryContext에 설정하여 동작을 실행합니다.

public class DeliveryMain {
    public static void main(String[] args) {
        DeliveryContext deliveryContext = new DeliveryContext();

        // 오토바이 배송 전략 설정
        deliveryContext.setDeliveryStrategy(new MotorcycleDelivery());
        deliveryContext.deliverPackage("소형 패키지"); // "오토바이로 소형 패키지를 배송합니다."

        // 트럭 배송 전략 설정
        deliveryContext.setDeliveryStrategy(new TruckDelivery());
        deliveryContext.deliverPackage("대형 패키지"); // "트럭으로 대형 패키지를 배송합니다."

        // 드론 배송 전략 설정
        deliveryContext.setDeliveryStrategy(new DroneDelivery());
        deliveryContext.deliverPackage("긴급 패키지"); // "드론으로 긴급 패키지를 배송합니다."
    }
}

새로운 배송 방법 추가 : 기차 배송

새로운 배송 방법을 추가할 때 DeliveryStrategy를 구현한 클래스를 추가하면 됩니다.

public class TrainDelivery implements DeliveryStrategy {
    @Override
    public void deliver(String packageDetails) {
        System.out.println("기차로 " + packageDetails + "를 배송합니다.");
    }
}

전략 패턴의 주요 장점

1. 확장성 : 새로운 전략(배송 방법)을 추가할 때 기존 코드를 수정하지 않아도 됩니다.

2. 유지보수성 : 조건문이 사라지고, 각 전략이 독립적으로 관리되며 유지보수가 용이해집니다.

3. 유연성 : 런타임에 전략을 동적으로 변경할 수 있습니다.

4. OCP 준수 : 기존 코드를 수정하지 않고 새로운 기능을 추가할 수 있어 개방-폐쇄 원칙을 준수합니다.

전략 패턴 단점

1. 클래스 증가 : 각 전략마다 별도의 클래스를 만들어야 하므로 클래스 수가 증가할 수 있습니다.

2. 간단한 경우에는 과도한 설계 : 전략이 적거나 간단한 경우 불필요하게 복잡해질 수 있습니다.

 

728x90

'JAVA' 카테고리의 다른 글

Call By Value와 Call By Reference  (0) 2024.03.03
JPA를 이용한 복합키(Composite Key) 매핑  (0) 2024.01.02
SOLID  (0) 2023.11.11