[Behavioral Pattern] 전략 패턴 (Strategy Pattern)
Design Pattern / Behavioral Pattern
전략 패턴의 정의와 해당 디자인 패턴의 예제 코드를 통한 이해 및 설명 정리
개념
- 실행(런타일) 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴
여기서 ‘전략’이란 일종의 알고리즘이 될 수도 있으며, 기능이나 동작이 될 수도 있는 특정한 목표를 수행하기 위한 행동 계획을 말함
- 즉, 어떤 일을 수행하는 알고리즘이 여러가지일 때, 동작들을 미리 전략으로 정의함으로써 손쉽게 전략을 교체할 수 있는, 알고리즘 변형이 빈번하게 필요한 경우에 적합한 패턴
패턴 구조
ConcreteStrategy1~3
(전략 알고리즘 객체들)- 알고리즘, 행위, 동작을 객체로 정의한 구현체
Strategy
(전략 인터페이스)- 모든 전략 구현체에 대한 공용 인터페이스
Context
(컨텍스트)- 알고리즘을 실행해야 할 때마다 해당 알고리즘과 연결된 전략 객체의 메소드를 호출
Client
(클라이언트)- 특정 전략 객체를 컨텍스트에 전달 함으로써 전략을 등록하거나 변경하여 전략 알고리즘을 실행한 결과를 누림
GoF
에서의 전략 패턴의 정의
동일 계열의 알고리즘군을 정의하고
→ 전략 구현체로 정의
각각의 알고리즘을 캡슐화하여
→ 인터페이스로 추상화
이들을 상호 교환이 가능하도록 만들고,
→ 합성(
composition
)으로 구성알고리즘을 사용하는 클라이언트와 상관없이 독립적으로
→ 컨텍스트 객체 수정 없이
알고리즘을 다양하게 변경할 수 있게 함
→ 메소드를 통해 전략 객체를 실시간으로 변경함으로써 전략을 변경
예제 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// Run | Walk 전략 (추상화된 알고리즘)
interface MoveStrategy {
move(): void;
}
class Walk implements MoveStrategy {
public move(): void {
console.log("걸어서 배달합니다.");
}
}
class Run implements MoveStrategy {
public move(): void {
console.log("뛰어서 배달합니다.");
}
}
// 한국어 | 일본어 번역 전략 (추상화된 알고리즘)
interface TranslateStrategy {
translate(): void;
}
class Korean implements TranslateStrategy {
public translate(): void {
console.log("한국어로 번역합니다.");
}
}
class Japanese implements TranslateStrategy {
public translate(): void {
console.log("일본어로 번역합니다.");
}
}
// Context (전략 등록 / 실행)
class Robot {
moveStrategy: MoveStrategy;
translateStrategy: TranslateStrategy;
constructor(
moveStrategy: MoveStrategy,
translateStrategy: TranslateStrategy
) {
this.moveStrategy = moveStrategy;
this.translateStrategy = translateStrategy;
}
move(): void {
this.moveStrategy.move();
}
translate(): void {
this.translateStrategy.translate();
}
setMove(moveStrategy: MoveStrategy) {
this.moveStrategy = moveStrategy;
}
setTranslate(translateStrategy: TranslateStrategy) {
this.translateStrategy = translateStrategy;
}
}
// Client (전략 교체 / 전략 실행한 결과를 얻음)
class User {
public static main(_args?: string[]): void {
const robot: Robot = new Robot(new Walk(), new Korean());
robot.move(); // 걸어서 배달합니다.
robot.translate(); // 한국어로 번역합니다.
console.log("");
// 로봇의 전략(기능)을 Run과 일본어 번역으로 변경
robot.setMove(new Run());
robot.setTranslate(new Japanese());
robot.move(); // 뛰어서 배달합니다.
robot.translate(); // 일본어로 번역합니다.
}
}
User.main();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// 전략 (추상화된 알고리즘)
interface PaymentStrategy {
pay(amount: number): void;
}
class KakaoCardStrategy implements PaymentStrategy {
private name: string;
private cardNumber: number;
private cvv: number;
private dateOfExpire: string;
constructor(
name: string,
cardNumber: number,
cvv: number,
dateOfExpire: string
) {
this.name = name;
this.cardNumber = cardNumber;
this.cvv = cvv;
this.dateOfExpire = dateOfExpire;
}
public pay(amount: number): void {
console.log(`${amount}₩ paid using Kakao Card`);
}
}
class LunaCardStrategy implements PaymentStrategy {
private email: string;
private password: string;
constructor(email: string, password: string) {
this.email = email;
this.password = password;
}
public pay(amount: number): void {
console.log(`${amount}₩ paid using Luna Card`);
}
}
class Item {
public name: string;
public price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
// Context (전략 등록 / 실행)
class ShoppingCart {
items: Item[];
constructor() {
this.items = new Array<Item>();
}
public addItem(item: Item): void {
this.items.push(item);
}
// 전략은 매개변수로 받아서 바로 전략을 실행
public pay(paymentMethod: PaymentStrategy): void {
let amount: number = 0;
for (let item of this.items) {
amount += item.price;
}
paymentMethod.pay(amount);
}
}
// Client (전략 제공 / 설정)
class PayUser {
public static main(_args?: string[]): void {
// 쇼핑카트 전략 Context 등록
const cart: ShoppingCart = new ShoppingCart();
// 쇼핑 물품
const A: Item = new Item("맥북 에어", 10000);
const B: Item = new Item("맥북 프로", 30000);
cart.addItem(A);
cart.addItem(B);
// Luna Card로 결제 전략 실행
cart.pay(new LunaCardStrategy("han1210_36@naver.com", "password1234"));
// Kakao Card로 결제 전략 실행
cart.pay(new KakaoCardStrategy("HyungJinHan", 123456789, 123, "12/10"));
}
}
PayUser.main();
참고한 출처 사이트
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.