设计模式-策略模式

Strategy

策略模式定义一系列算法,可在不影响客户端代码的情况下相互替换

  • 当存在多种算法需要动态选择时可使用策略模式
  • 策略与客户端代码间耦合度降低、策略本身可扩展、客户端代码可动态切换策略
  • 封装算法本身会增加代码复杂度,客户端代码必须知晓策略间的不同

CPP

基本结构

Member FullName Description
策略接口 Strategy 声明所有具体策略类方法
具体策略类 Concrete Strategy 基于接口完成不同策略实现
上下文类 Context 维护策略对象的引用

UML结构图

实现步骤

  1. 定义策略接口
1
2
3
4
5
class Strategy {
public:
virtual ~Strategy() = default;
virtual void execute(int x, int y) const = 0; // 策略方法
};
  1. 定义具体策略类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class AddStrategy : public Strategy {
public:
void execute(int x, int y) const override {
std::cout << "Result:" << x + y << std::endl;
}
};

class SubtractStrategy : public Strategy {
public:
void execute(int x, int y) const override {
std::cout << "Result:" << x - y << std::endl;
}
};

class MultiplyStrategy : public Strategy {
public:
void execute(int x, int y) const override {
std::cout << "Result:" << x * y << std::endl;
}
};
  1. 定义上下文类
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
// 上下文类
class Context {
private:
Strategy* _strategy;

public:
explicit Context(Strategy* strategy = nullptr) : _strategy(strategy) {}

~Context() {
delete _strategy;
}

void setStrategy(Strategy* strategy) {
delete _strategy;
_strategy = strategy;
}

void executeStrategy(int x, int y) const {
if (_strategy != nullptr) {
_strategy->execute(x, y);
} else {
std::cout << "Error strategy" << std::endl;
}
}
};
  1. 调用策略
1
2
3
4
5
6
7
8
9
10
Context context;

context.setStrategy(new AddStrategy());
context.executeStrategy(5, 3);

context.setStrategy(new SubtractStrategy());
context.executeStrategy(5, 3);

context.setStrategy(new MultiplyStrategy());
context.executeStrategy(5, 3);

Fortran

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
module StrategyInterface
implicit none
type, abstract :: StrategyType
contains
procedure(strategyExecute), deferred :: execute
end type StrategyType

abstract interface
subroutine strategyExecute(this, x, y, result)
import :: StrategyType
class(StrategyType), intent(in) :: this
integer, intent(in) :: x, y
integer, intent(out) :: result
end subroutine strategyExecute
end interface
end module StrategyInterface

module AddStrategyModule
use StrategyInterface
implicit none
type, extends(StrategyType) :: AddStrategy
contains
procedure :: execute => addExecute
end type AddStrategy
contains
subroutine addExecute(this, x, y, result)
class(AddStrategy), intent(in) :: this
integer, intent(in) :: x, y
integer, intent(out) :: result
result = x + y
end subroutine addExecute
end module AddStrategyModule

module SubtractStrategyModule
use StrategyInterface
implicit none
type, extends(StrategyType) :: SubtractStrategy
contains
procedure :: execute => subtractExecute
end type SubtractStrategy
contains
subroutine subtractExecute(this, x, y, result)
class(SubtractStrategy), intent(in) :: this
integer, intent(in) :: x, y
integer, intent(out) :: result
result = x - y
end subroutine subtractExecute
end module SubtractStrategyModule

module MultiplyStrategyModule
use StrategyInterface
implicit none
type, extends(StrategyType) :: MultiplyStrategy
contains
procedure :: execute => multiplyExecute
end type MultiplyStrategy
contains
subroutine multiplyExecute(this, x, y, result)
class(MultiplyStrategy), intent(in) :: this
integer, intent(in) :: x, y
integer, intent(out) :: result
result = x * y
end subroutine multiplyExecute
end module MultiplyStrategyModule

module ContextModule
use StrategyInterface
implicit none
type :: Context
private
class(StrategyType), allocatable :: strategy
contains
procedure :: setStrategy => setStrategyProc
procedure :: executeStrategy => executeStrategyProc
end type Context
contains
subroutine setStrategyProc(this, strategy)
class(Context), intent(inout) :: this
class(StrategyType), intent(in) :: strategy
if (allocated(this%strategy)) then
deallocate(this%strategy)
end if
allocate(this%strategy, source=strategy)
end subroutine setStrategyProc

subroutine executeStrategyProc(this, x, y, result)
class(Context), intent(in) :: this
integer, intent(in) :: x, y
integer, intent(out) :: result
if (allocated(this%strategy)) then
call this%strategy%execute(x, y, result)
else
write(*, *) "Error - strategy not set"
end if
end subroutine executeStrategyProc
end module ContextModule

program main
use ContextModule
use AddStrategyModule
use SubtractStrategyModule
use MultiplyStrategyModule
implicit none
type(Context) :: cont
integer :: result

call cont%setStrategy(AddStrategy())
call cont%executeStrategy(5, 3, result)
write(*, *) "Result: ", result

call cont%setStrategy(SubtractStrategy())
call cont%executeStrategy(5, 3, result)
write(*, *) "Result: ", result

call cont%setStrategy(MultiplyStrategy())
call cont%executeStrategy(5, 3, result)
write(*, *) "Result: ", result

end program main

Reference

refactoringgur | 设计模式 策略模式
未平 | C++ 设计模式 策略模式 The Strategy Pattern
wx_幼儿园的学霸 | C++设计模式——策略模式(Strategy Pattern)

0%