전략 패턴이란
전략 패턴은 여러 가지 방법(알고리즘)을 미리 만들어 놓고, 필요할 때 그중 하나를 골라 사용하는 것입니다. 이렇게 하면 필요할 때마다 새로운 방법을 쉽게 추가할 수 있습니다.
전략 패턴을 사용 시 이점
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. 간단한 경우에는 과도한 설계 : 전략이 적거나 간단한 경우 불필요하게 복잡해질 수 있습니다.
'JAVA' 카테고리의 다른 글
Call By Value와 Call By Reference (0) | 2024.03.03 |
---|---|
JPA를 이용한 복합키(Composite Key) 매핑 (0) | 2024.01.02 |
SOLID (0) | 2023.11.11 |