策略模式(Strategy Pattern)工程规范与实现(Go / Rust 双语言)
策略模式(Strategy Pattern)工程规范与实现(Go / Rust 双语言)
1 概述
1.1 定义
策略模式属于行为型设计模式,定义一系列可互换的算法(策略),将每一种算法独立封装,使算法的变化与使用者解耦。
核心思想:封装变化、算法可替换、运行时动态切换。
工程角色(精简版):
- Strategy(策略接口):统一算法行为规范
- ConcreteStrategy(具体策略):不同实现算法逻辑
1.2 适用场景
推荐使用
- 同一业务存在多种分支算法,且需要动态切换(加密、校验、排序、计费、日志格式);
- 大量if/else、switch 分支臃肿,需要消除分支嵌套;
- 算法逻辑频繁迭代新增,希望新增策略不改动上下文代码(开闭原则);
- 需要统一管控多种算法生命周期、统一入参出参规范。
避免滥用
- 算法固定、几乎无变更、无需切换;
- 仅少量分支,过度拆分导致类/结构体爆炸、增加维护成本。
1.3 解决核心痛点
- 消灭业务层冗长 if/else、分支嵌套;
- 算法逻辑独立隔离,单一职责,便于单元测试;
- 支持运行时动态替换策略,灵活适配不同场景;
- 新增算法无需修改上层逻辑,符合开闭原则。
核心原则:变的是算法,不变的是调用方式。
2 通用编码规范
- 定义统一策略接口,约束所有算法入参、出参、行为;
- 每一种算法独立实现一个策略类/结构体,禁止策略内部混杂多种分支;
- 通过 Context 上下文 统一调度,业务层只依赖上下文,不依赖具体策略;
- 支持运行时动态替换策略实例;
- 策略无状态优先,保证可复用、线程安全;
- 策略枚举映射统一收口,集中注册、方便遍历与兜底。
3 Go 标准实现
Go 采用 接口 + 多结构体实现 + Context 上下文 标准工程写法,彻底消除 if-else。
3.1 完整代码实现
package main
import "fmt"
// ====================== 策略接口 ======================
// SortStrategy 统一排序策略接口,规范算法行为
type SortStrategy interface {
Sort([]int) []int
}
// ====================== 具体策略实现 ======================
// AscSort 升序排序策略(无状态、可全局复用)
type AscSort struct{}
// Sort 实现升序排序逻辑
func (a *AscSort) Sort(arr []int) []int {
res := make([]int, len(arr))
copy(res, arr)
for i := 0; i < len(res); i++ {
for j := i + 1; j < len(res); j++ {
if res[i] > res[j] {
res[i], res[j] = res[j], res[i]
}
}
}
return res
}
// DescSort 降序排序策略(无状态、可全局复用)
type DescSort struct{}
// Sort 实现降序排序逻辑
func (d *DescSort) Sort(arr []int) []int {
res := make([]int, len(arr))
copy(res, arr)
for i := 0; i < len(res); i++ {
for j := i + 1; j < len(res); j++ {
if res[i] < res[j] {
res[i], res[j] = res[j], res[i]
}
}
}
return res
}
// ====================== 上下文 Context ======================
// SortContext 策略调度上下文,统一入口、动态切换策略
type SortContext struct {
strategy SortStrategy
}
// NewSortContext 初始化调度上下文
func NewSortContext() *SortContext {
return &SortContext{}
}
// SetStrategy 运行时动态替换排序策略
func (c *SortContext) SetStrategy(s SortStrategy) {
c.strategy = s
}
// Execute 统一执行算法,兜底空策略,避免空指针panic
func (c *SortContext) Execute(arr []int) []int {
if c.strategy == nil {
return arr
}
return c.strategy.Sort(arr)
}
func main() {
// 测试数据
data := []int{3, 1, 4, 2, 5}
ctx := NewSortContext()
// 切换升序策略执行
ctx.SetStrategy(&AscSort{})
fmt.Println("升序排序结果:", ctx.Execute(data))
// 动态切换降序策略执行
ctx.SetStrategy(&DescSort{})
fmt.Println("降序排序结果:", ctx.Execute(data))
}
3.2 Go 专项约束
- 策略结构体尽量无状态,全局可复用,减少内存分配;
- 禁止在单个策略实现内写多分支逻辑;
- 业务层只依赖 Context,不直接依赖具体策略结构体;
- 可配合 map 实现策略注册器,统一路由分发。
3.3 工程进阶:策略注册器(完整版、无分支路由)
通过注册器统一收口所有策略,基于枚举/标识自动路由,业务层零 if/else,支持动态注册、兜底容错,适配企业级多策略迭代场景。
package main
import (
"fmt"
"sync"
)
// ====================== 策略枚举标识 ======================
type SortType string
const (
SortAsc SortType = "asc"
SortDesc SortType = "desc"
)
// ====================== 策略接口 ======================
type SortStrategy interface {
Sort([]int) []int
}
// ====================== 具体策略 ======================
type AscSort struct{}
func (a *AscSort) Sort(arr []int) []int {
res := make([]int, len(arr))
copy(res, arr)
for i := 0; i < len(res); i++ {
for j := i + 1; j < len(res); j++ {
if res[i] > res[j] {
res[i], res[j] = res[j], res[i]
}
}
}
return res
}
type DescSort struct{}
func (d *DescSort) Sort(arr []int) []int {
res := make([]int, len(arr))
copy(res, arr)
for i := 0; i < len(res); i++ {
for j := i + 1; j < len(res); j++ {
if res[i] < res[j] {
res[i], res[j] = res[j], res[i]
}
}
}
return res
}
// ====================== 策略注册器(核心) ======================
var (
strategyRegister = make(map[SortType]SortStrategy)
registerMu sync.RWMutex
)
// RegisterStrategy 注册策略
func RegisterStrategy(t SortType, s SortStrategy) {
registerMu.Lock()
defer registerMu.Unlock()
strategyRegister[t] = s
}
// GetStrategy 获取策略(带兜底)
func GetStrategy(t SortType) SortStrategy {
registerMu.RLock()
defer registerMu.RUnlock()
// 默认升序兜底
if s, ok := strategyRegister[t]; ok {
return s
}
return &AscSort{}
}
// ====================== 上下文 ======================
type SortContext struct {
strategy SortStrategy
}
func NewSortContext() *SortContext {
return &SortContext{}
}
func (c *SortContext) SetStrategy(s SortStrategy) {
c.strategy = s
}
func (c *SortContext) Execute(arr []int) []int {
if c.strategy == nil {
return arr
}
return c.strategy.Sort(arr)
}
// ====================== 初始化注册 ======================
func init() {
RegisterStrategy(SortAsc, &AscSort{})
RegisterStrategy(SortDesc, &DescSort{})
}
func main() {
data := []int{3, 1, 4, 2, 5}
ctx := NewSortContext()
// 基于标识自动路由,无任何分支
ctx.SetStrategy(GetStrategy(SortAsc))
fmt.Println("注册器-升序:", ctx.Execute(data))
ctx.SetStrategy(GetStrategy(SortDesc))
fmt.Println("注册器-降序:", ctx.Execute(data))
// 非法类型自动兜底
ctx.SetStrategy(GetStrategy("unknown"))
fmt.Println("非法策略-兜底升序:", ctx.Execute(data))
}
Go 注册器核心优势
- 新增策略只需实现接口+注册,无需修改路由逻辑,完全符合开闭原则;
- 读写锁保障并发安全,支持运行时动态注册策略;
- 天然兜底机制,避免策略不存在导致业务异常;
- 彻底消灭业务层分支判断,路由逻辑统一收口。
4 Rust 标准实现
Rust 工程标准方案:Trait 策略接口 + 多实现结构体 + Context 上下文,零开销抽象、安全可控。
4.1 完整代码实现
// ====================== 策略 Trait ======================
pub trait SortStrategy {
fn sort(&self, arr: &[i32]) -> Vec<i32>;
}
// ====================== 具体策略 ======================
/// 升序策略
#[derive(Default)]
pub struct AscSort;
impl SortStrategy for AscSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort();
res
}
}
/// 降序策略
#[derive(Default)]
pub struct DescSort;
impl SortStrategy for DescSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort_by(|a, b| b.cmp(a));
res
}
}
// ====================== 上下文 Context ======================
pub struct SortContext {
strategy: Option<Box<dyn SortStrategy>>,
}
impl SortContext {
pub fn new() -> Self {
Self { strategy: None }
}
// 动态设置策略
pub fn set_strategy(&mut self, s: Box<dyn SortStrategy>) {
self.strategy = Some(s);
}
// 统一执行入口
pub fn execute(&self, arr: &[i32]) -> Vec<i32> {
self.strategy.as_ref().map(|s| s.sort(arr)).unwrap_or(arr.to_vec())
}
}
fn main() {
let data = [3, 1, 4, 2];
let mut ctx = SortContext::new();
ctx.set_strategy(Box::new(AscSort::default()));
println!("升序:{:?}", ctx.execute(&data));
ctx.set_strategy(Box::new(DescSort::default()));
println!("降序:{:?}", ctx.execute(&data));
}
4.2 工程进阶:策略注册器(完整版、静态映射+容错路由)
Rust 基于枚举+静态注册实现零开销策略路由,无动态哈希表开销,编译期校验合法策略,运行时兜底容错,适配高性能工程场景。
use std::collections::HashMap;
use std::sync::OnceLock;
// ====================== 策略枚举标识 ======================
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SortType {
Asc,
Desc,
}
// ====================== 策略 Trait 接口 ======================
pub trait SortStrategy {
fn sort(&self, arr: &[i32]) -> Vec<i32>;
}
// ====================== 具体策略实现 ======================
#[derive(Debug, Default)]
pub struct AscSort;
impl SortStrategy for AscSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort_unstable();
res
}
}
#[derive(Debug, Default)]
pub struct DescSort;
impl SortStrategy for DescSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort_unstable_by(|a, b| b.cmp(a));
res
}
}
// ====================== 策略注册器(静态全局) ======================
static STRATEGY_REGISTER: OnceLock<HashMap<SortType, Box<dyn SortStrategy + Send + Sync>>> = OnceLock::new();
/// 初始化所有策略(程序启动一次性注册)
fn init_strategy_register() -> HashMap<SortType, Box<dyn SortStrategy + Send + Sync>> {
let mut map = HashMap::<SortType, Box<dyn SortStrategy + Send + Sync>>::new();
map.insert(SortType::Asc, Box::new(AscSort::default()));
map.insert(SortType::Desc, Box::new(DescSort::default()));
map
}
/// 根据类型获取策略,默认升序兜底
pub fn get_strategy(typ: SortType) -> &'static Box<dyn SortStrategy + Send + Sync> {
let register = STRATEGY_REGISTER.get_or_init(init_strategy_register);
register.get(&typ).unwrap_or_else(|| register.get(&SortType::Asc).unwrap())
}
// ====================== 上下文 ======================
pub struct SortContext {
strategy: Option<&'static Box<dyn SortStrategy + Send + Sync>>,
}
impl SortContext {
pub fn new() -> Self {
Self { strategy: None }
}
pub fn set_strategy(&mut self, s: &'static Box<dyn SortStrategy + Send + Sync>) {
self.strategy = Some(s);
}
pub fn execute(&self, arr: &[i32]) -> Vec<i32> {
self.strategy.as_ref().map(|s| s.sort(arr)).unwrap_or_else(|| arr.to_vec())
}
}
fn main() {
let data = [3, 1, 4, 2, 5];
let mut ctx = SortContext::new();
// 枚举路由,零分支
ctx.set_strategy(get_strategy(SortType::Asc));
println!("注册器-升序:{:?}", ctx.execute(&data));
ctx.set_strategy(get_strategy(SortType::Desc));
println!("注册器-降序:{:?}", ctx.execute(&data));
}
Rust 注册器核心优势
- 基于 OnceLock 静态一次性初始化,零重复开销、线程安全;
- 枚举管控策略类型,编译期拦截非法策略标识,减少运行时异常;
- 绑定 Send + Sync,支持全局多线程共享策略实例;
- 静态引用复用实例,无频繁堆分配,性能优于动态注册方案。
4.3 Rust 进阶:泛型静态分发(零开销、编译期绑定)
前文 Box
泛型静态分发通过编译器单态化实现编译期策略绑定,无虚表、无运行时开销,是 Rust 策略模式最高性能方案,适合策略固定、无需运行时动态切换的高性能场景。
// ====================== 策略 Trait(静态分发专用) ======================
pub trait SortStrategy {
fn sort(&self, arr: &[i32]) -> Vec<i32>;
}
// ====================== 具体策略实现 ======================
#[derive(Debug, Default)]
pub struct AscSort;
impl SortStrategy for AscSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort_unstable();
res
}
}
#[derive(Debug, Default)]
pub struct DescSort;
impl SortStrategy for DescSort {
fn sort(&self, arr: &[i32]) -> Vec<i32> {
let mut res = arr.to_vec();
res.sort_unstable_by(|a, b| b.cmp(a));
res
}
}
// ====================== 泛型上下文(静态分发核心) ======================
/// 泛型约束:编译期绑定具体策略类型,零开销抽象
pub struct SortContext<S: SortStrategy> {
strategy: S,
}
impl<S: SortStrategy> SortContext<S> {
// 构造方法:传入任意实现策略 trait 的实例
pub fn new(strategy: S) -> Self {
Self { strategy }
}
// 统一执行入口,编译期确定具体实现
pub fn execute(&self, arr: &[i32]) -> Vec<i32> {
self.strategy.sort(arr)
}
}
fn main() {
let data = [3, 1, 4, 2, 5];
// 编译期绑定升序策略
let asc_ctx = SortContext::new(AscSort::default());
println!("静态分发-升序:{:?}", asc_ctx.execute(&data));
// 编译期绑定降序策略
let desc_ctx = SortContext::new(DescSort::default());
println!("静态分发-降序:{:?}", desc_ctx.execute(&data));
}
4.4 静态分发专项规范
- 泛型上下文必须约束 S: SortStrategy,保证编译期类型安全;
- 策略优先无状态设计,可直接通过 Default 构造,零内存分配;
- 追求极致性能场景优先静态分发,业务动态灵活场景选用动态分发;
- 静态分发无法配合运行时注册器,仅适用于编译期已知的固定策略集合。
4.5 Rust 专项约束
- 使用 dyn Trait 特征对象实现动态分发,支持运行时策略切换;
- 策略结构体设计为无状态静态常量,全局零拷贝复用,性能最优;
- Trait 约束 Send + Sync,天然支持多线程并发安全;
- 接口保持单一职责,仅定义核心算法行为,杜绝冗余方法;
- 统一静态注册方案,彻底修复特征对象类型不匹配编译错误;
4.6 静态分发 vs 动态分发 核心差异
| 对比维度 | 静态分发(泛型) | 动态分发(dyn Trait) |
|---|---|---|
| 绑定时机 | 编译期确定具体策略类型 | 运行时动态匹配策略实现 |
| 运行时开销 | 零开销、无虚表跳转 | 存在虚表查表微小开销 |
| 策略切换 | 不支持运行时动态切换 | 支持运行时随时替换策略 |
| 二进制体积 | 略大(单态化生成多份代码) | 更小(共用一套分发逻辑) |
| 适用场景 | 高性能、策略固定、无需动态切换 | 业务灵活、需动态路由、适配注册器 |
5 Go / Rust 策略模式核心对比
| 对比维度 | Go | Rust |
|---|---|---|
| 抽象能力 | Interface 隐式实现 | Trait 显式实现 |
| 多态方式 | 接口指针动态多态 | dyn Trait 特征对象多态 |
| 策略切换 | 运行时可动态替换 | 运行时可动态替换 |
| 性能开销 | 极低 | 零开销抽象 |
| 编译约束 | 无编译期强制校验 | 编译期严格校验实现 |
| 注册机制 | RWMutex+Map 动态注册 | OnceLock 静态一次性注册 |
| 适用场景 | 快速迭代、动态扩展策略 | 高性能、高可靠、强规范项目 |
6 最佳实践与常见误区
6.1 常见误区
- 策略内部继续写大量 if/else,没有真正解耦分支;
- 过度拆分策略,简单逻辑强行拆类,造成代码碎片化;
- 上下文混入业务逻辑,违背「调度与实现分离」;
- 策略带大量可变状态,引发并发数据竞争;
- 业务层直接调用具体策略,绕过上下文统一管控。
6.2 最佳实践
- 分支多、迭代频繁必用策略模式,彻底消灭臃肿判断;
- 所有具体策略单一职责、互相独立,新增策略无需改旧代码;
- 上下文仅负责策略持有、切换、调度,不实现具体算法;
- 策略设计为无状态,全局复用,提升性能、减少内存分配;
- 可扩展策略注册器,通过枚举/字符串自动路由策略,进一步简化业务层。

浙公网安备 33010602011771号