1. 전략패턴(Strategy Pattern)이란?
전략 패턴(Strategy Pattern)은 객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략(알고리즘)을 객체화하여 동적으로 행위를 변경할 수 있게 해주는 디자인 패턴이다. 이 패턴은 여러 알고리즘을 하나의 추상적인 인터페이스로 묶어 알고리즘군을 정의하고, 각 알고리즘을 구체적인 전략 클래스로 캡슐화하여 필요에 따라 서로 교체 가능하게 만든다. 이를 통해 클라이언트는 알고리즘의 내부 구조를 알 필요 없이 유연하게 알고리즘을 변경할 수 있다.
알고리즘군이란?
- 동일한 기능을 수행하지만 다른 방식으로 구현된 알고리즘들의 모음
예)
- "정렬"이라는 동일한 문제를 해결하는 알고리즘 군 안에는 버블정렬, 삽입정렬, 퀵정렬, 병합정렬 등이 있다.
- 이 알고리즘 군에 들어있는 알고리즘들은 모두 "정렬"이라는 동일한 문제를 해결하지만, 각각의 알고리즘은 다른 방식으로 동작한다.
2. 전략 패턴의 주요 장점
1. 유연성 제공:
전략 패턴은 알고리즘을 쉽게 교체할 수 있는 유연성을 제공한다. 예를 들어, 특정 기능을 수행하는 여러 가지 방법이 있을 때, 이 패턴을 사용하면 런타임에 알고리즘을 변경할 수 있다. 이는 다양한 상황에 따라 동적으로 행위를 변경할 수 있게 해준다.
2. 코드 재사용성 향상:
알고리즘을 별도의 클래스나 객체로 분리하여 재사용할 수 있게 한다. 여러 클라이언트 객체가 동일한 알고리즘을 공유할 수 있으며, 코드 중복을 줄여준다. 이는 코드의 유지보수를 용이하게 한다.
3. 유지보수성 향상:
알고리즘을 각기 다른 클래스에 캡슐화함으로써, 특정 알고리즘의 변경이 다른 코드에 영향을 미치지 않는다. 이는 코드의 수정이 필요한 경우 변경의 범위를 최소화하여 유지보수를 쉽게 한다.
4. 확장성 증대:
새로운 알고리즘을 추가할 때 기존 코드를 수정할 필요 없이 새로운 전략 클래스를 추가하면 된다. 이는 시스템의 확장성을 크게 향상시킨다. 새로운 요구사항이 생길 때마다 간단히 새로운 전략을 추가할 수 있다.
3. 전략 패턴의 구조
전략 패턴은 다음과 같은 주요 구성 요소들로 이루어져 있다.
1. 컨텍스트(Context):
• 역할: 클라이언트가 사용할 인터페이스를 제공하며, 알고리즘을 동적으로 변경할 수 있게 해주는 클래스이다. 컨텍스트는 내부적으로 Strategy 객체를 유지하며, 이를 통해 클라이언트가 요청한 작업을 수행한다.
2. 전략 인터페이스(Strategy Interface):
• 역할: 알고리즘을 캡슐화하여 여러 알고리즘을 하나의 추상적인 인터페이스로 정의한다. 이를 통해 다양한 알고리즘을 동일한 방식으로 사용할 수 있게 한다.
3. 구체적인 전략 클래스들(Concrete Strategy Classes):
• 역할: 전략 인터페이스를 구현하여 실제 알고리즘을 제공하는 클래스들이다. 각 클래스는 특정 알고리즘을 구현하며, 컨텍스트에서 필요에 따라 이 알고리즘을 사용할 수 있다.
+--------------------+ +--------------------------+
| Context | | Strategy Interface |
|--------------------| |--------------------------|
| - strategy: Strategy |<>--------| + useAlgorithm(): void |
|--------------------| +--------------------------+
| + setStrategy(s: Strategy): void |
| + executeStrategy(): void |
+--------------------+
|
| uses
v
+-------------------------+
| Concrete Strategy A |
|-------------------------|
| + useAlgorithm(): void |
+-------------------------+
|
| uses
v
+-------------------------+
| Concrete Strategy B |
|-------------------------|
| + useAlgorithm(): void |
+-------------------------+
|
| uses
v
+-------------------------+
| Concrete Strategy C |
|-------------------------|
| + useAlgorithm(): void |
+-------------------------+
4. 예시
전략 패턴의 예시를 Player라는 클래스와 4개의 직업 - 전사, 궁수, 마법사, 성직자-, 그리고 각각의 무기 4개 - 검, 활, 지팡이, 메이스 - 로 구현해보자. 이 예시를 위에서 말한 전략 패턴의 주요 구성 요소에 아래와 같이 대입할 수 있다.
1. 컨텍스트(Context):
• Player 클래스는 무기 전략을 설정하고, 이를 사용하여 공격하는 역할을 한다. Player 객체는 무기 전략을 변경할 수 있으며, attack 메서드를 호출하면 현재 설정된 전략에 따라 공격 행동을 수행한다.
• 역할: 클라이언트가 사용할 인터페이스를 제공하며, 무기 사용 전략을 동적으로 변경할 수 있게 해준다.
• 예시: Player 클래스가 컨텍스트의 역할을 한다.
// 플레이어 클래스
class Player {
constructor(name, strategy) {
this.name = name;
this.setStrategy(strategy);
}
setStrategy(strategy) {
if (!(strategy instanceof WeaponStrategy)) {
throw new Error("전략은 WeaponStrategy의 인스턴스여야 합니다.");
}
this.strategy = strategy;
}
attack() {
console.log(`${this.name}이(가) ${this.strategy.useWeapon()}`);
}
}
2. 전략 인터페이스(Strategy Interface):
• WeaponStrategy 클래스는 무기 사용 방법을 정의하는 추상 클래스이다. useWeapon 메서드는 각 무기 전략 클래스가 구현해야 하는 메서드이다. 이 인터페이스를 통해 Player 클래스는 구체적인 무기 사용 방법을 알 필요 없이, 무기를 사용할 수 있다.
• 역할: 무기 사용 방법을 캡슐화하여 여러 무기 사용 전략을 하나의 추상적인 인터페이스로 정의한다.
• 예시: WeaponStrategy 클래스가 전략 인터페이스의 역할을 한다.
// WeaponStrategy 인터페이스
class WeaponStrategy {
useWeapon() {
throw new Error("useWeapon 메서드를 구현해야 합니다.");
}
}
3. 구체적인 전략 클래스들(Concrete Strategy Classes):
• 역할: 전략 인터페이스를 구현하여 실제 무기 사용 방법을 제공하는 클래스들이다. 각 클래스는 특정 무기 사용 방법을 구현한다.
• 예시: SwordStrategy, BowStrategy, StaffStrategy, MaceStrategy 클래스들이 구체적인 전략 클래스들이다.
// 구체적인 전략 클래스
class SwordStrategy extends WeaponStrategy {
useWeapon() {
return "검으로 공격합니다!";
}
}
class BowStrategy extends WeaponStrategy {
useWeapon() {
return "활로 공격합니다!";
}
}
class StaffStrategy extends WeaponStrategy {
useWeapon() {
return "지팡이로 공격합니다!";
}
}
class MaceStrategy extends WeaponStrategy {
useWeapon() {
return "메이스로 공격합니다!";
}
}
사용예시)
const warrior = new Player("전사", new SwordStrategy());
warrior.attack(); // 전사가 검으로 공격합니다!
const archer = new Player("궁수", new BowStrategy());
archer.attack(); // 궁수가 활로 공격합니다!
const mage = new Player("마법사", new StaffStrategy());
mage.attack(); // 마법사가 지팡이로 공격합니다!
const cleric = new Player("성직자", new MaceStrategy());
cleric.attack(); // 성직자가 메이스로 공격합니다!
'Learn to Code' 카테고리의 다른 글
[디자인패턴] 자바스크립트로 옵저버패턴(Observer pattern) 구현하기 (0) | 2024.06.24 |
---|---|
[디자인패턴] React + Tanstack Query 서비스 레이어 패턴으로 구조짜기 (0) | 2024.06.03 |
[디자인패턴] 요즘 가장 핫한 프론트엔드 디자인패턴: Feature Sliced Design (번역) (2) | 2024.06.03 |
[Next.js] 브라우저 캐싱 문제 해결 방법 (0) | 2023.10.20 |
[Next.js] 버전 13+으로 업데이트하기 (0) | 2023.10.07 |
댓글