- [CS 전공지식 노트] Topic 1. MVC 패턴
- [CS 전공지식 노트] Topic 2. 노출모듈패턴
- [CS 전공지식 노트] Topic 3. 전략패턴
- [CS 전공지식 노트] Topic 4. 네트워크
- [CS 전공지식 노트] Topic 5. HTTP
- [CS 전공지식 노트] Topic 6. 프로세스와 스레드
- [CS 전공지식 노트] Topic 7. 공유자원과 임계영역, 교착상태
- [CS 전공지식 노트] Topic 8. 선형 자료 구조
[CS 전공지식 노트] Topic 3. 전략패턴
전략패턴
전략 패턴은 많은 알고리즘이 있고 이들 중 하나를 선택해서 사용해야 할 때 유용한 디자인 패턴입니다. 전략 패턴은 구체적인 알고리즘을 캡슐화하여 동적으로 알고리즘을 선택할 수 있게 합니다.
전략 패턴은 OCP (Open-Closed Principle) 와 연계되는데, 이를 통해 기존 코드를 변경하지 않고도 알고리즘을 쉽게 변경하거나 확장할 수 있습니다.
OCP : 소프트웨어 구성요소(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다는 원칙입니다.
OCP 위반 코드
아래는 OCP 원칙을 위반한 코드입니다.
class Order {
void processCreditCardPayment() {
// 카드 결제 처리
}
void processPaypalPayment() {
// Paypal 결제 처리
}
}
만약 현금 결제라는 새로운 결제 방법이 추가된다면 어떻게 할까요? 아래와 같이 수정해야 합니다.
class Order {
void processCreditCardPayment() {
// 카드 결제 처리
}
void processPaypalPayment() {
// Paypal 결제 처리
}
void cashPayment() {
// Paypal 결제 처리
}
}
하나의 메서드인 pay()
로 만든다고 해도 아래 정도일 겁니다.
class Order {
public void pay(String paymentMethod){
if(paymentMethod.equals(...))
else if(paymentMethod.equals(...))
else ifpaymentMethod.equals(...)
}
void processCreditCardPayment() {
// 카드 결제 처리
}
void processPaypalPayment() {
// Paypal 결제 처리
}
void cashPayment() {
// Paypal 결제 처리
}
}
이렇게 수정하는 방식은 SOLID의 원칙 중 OCP( Open-Closed Principle )에 위배됩니다. OCP에 의하면 기존의 코드는 수정하지 않으면서 행위가 수정되어야 하지만, 지금은 Order
에 메서드를 추가하거나 pay()
메서드를 직접 수정했습니다.
또한 지금과 같은 방식의 변경은 시스템이 확장이 되었을 때 유지보수를 어렵게 합니다. 계속해서 결제방법이 변경되거나 추가될 때 Order
클래스를 일일히 수정해줘야 하기 때문입니다.
전략 패턴을 통한 해결
이를 해결하기 위해, 전략패턴을 이용해 변경되는 부분(결제방법, PaymentMethod
) 은 별도로 분리하겠습니다.
interface PaymentMethod {
void processPayment();
}
class CreditCardPayment implements PaymentMethod {
@Override
public void processPayment() {
// 카드 결제 처리
}
}
class PaypalPayment implements PaymentMethod {
@Override
public void processPayment() {
// Paypal 결제 처리
}
}
class Order {
private PaymentMethod paymentMethod;
public Order(PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
}
void processPayment() {
paymentMethod.processPayment();
}
}
Order
클래스는 생성자를 통해 결제방법(PaymentMethod
) 를 받아서 처리합니다.
Context
는 내부에 Strategy
필드를 가지고 있습니다. 이 필드에 변하는 부분인 Strategy
의 구현체를 주입하면 됩니다. 전략 패턴의 핵심은 Context
는 Strategy
인터페이스에만 의존한다는 점입니다. 덕분에 Strategy
의 구현체를 변경하거나 새로 만들어도 Context
코드에는 영향을 주지 않습니다.
즉, 전략패턴은 기존의 코드 변경 없이 행위를 자유롭게 바꿀 수 있게 해주는, OCP 를 준수한 디자인 패턴입니다.
그리고 스프링에서 의존관계 주입에서 사용하는 방식이 바로 전략 패턴입니다.
댓글남기기