[Golang修仙之路] 策略模式

1. 什么是「策略模式」?

个人的理解就是, 实现同一件事情, 可能有不同的算法/策略, 通过使用策略模式, 可以让策略的选择更平滑, 添加/删除一个策略更方便(因为符合开闭原则, 扩展性更好).

2. 策略模式的实现

首先要定义一个策略接口, 有若干不同策略的具体实现去实现这个接口. 然后对于策略的使用者, 只需要依赖抽象的策略接口, 然后通过一个SetStrategy()设置策略的方法, 来指明当前抽象接口选择哪个具体实现(这也是多态的体现). 最后调用抽象策略接口定义的具体方法即可.

2.1 具体场景Demo

光这样说肯定不好理解, 下面我来举1个例子, 这个例子的场景是我自己想的, 不是抄的.

篮球场上有多种不同的防守战术, 我们认为每一种战术是一个「策略」.

首先定义防守策略接口:

golang 复制代码
package interfaces

type Defend interface {
	Defend()
}

然后写几个具体实现, 意思一下hhh

golang 复制代码
// strategy 1
type Focus struct{}

func (f *Focus) Defend() {
	fmt.Println("执行盯人包夹防守战术")
}

// strategy 2
type OneOnOne struct{}

func (o *OneOnOne) Defend() {
	fmt.Println("执行一对一防守战术")
}

// strategy 3
type TwoThree struct{}

func (t *TwoThree) Defend() {
	fmt.Println("执行二三联防战术")
}

然后通过一个很多文章上叫Context的类, 去承担 设置策略 + 执行策略 的工作. 我们这里搞了一个 Coach教练类, 来设置防守战术 并 敦促队员执行.

可以看到, Coach类内部确实只依赖接口, Coach对策略的增加/减少是无感的, 扩展性好.

golang 复制代码
type Coach struct {
	name string
	defendStrategy interfaces.Defend
}

func (c *Coach) SetDefendStrategy(strategy interfaces.Defend) {
	fmt.Printf("%s 切换防守策略\n", c.name)
	c.defendStrategy = strategy
}

func (c *Coach) ExecuteDefend() {
	c.defendStrategy.Defend()
}

func NewCoach(name string) *Coach {
	return &Coach{
		name: name,
	}
}

最后我们执行main函数, 并看一下效果:

golang 复制代码
func main() {
    coach := NewCoach("波波维奇")
    coach.SetDefendStrategy(&strategies.Focus{})
    coach.ExecuteDefend()

    coach.SetDefendStrategy(&strategies.OneOnOne{})
    coach.ExecuteDefend()
}

程序运行成功, 但是我们注意到, 在main函数中, 我们确实要创建策略的具体实现的实例来作为参数传入, 这一点也被归为策略模式的缺点之一. 但是我认为, 不这么写还能怎么写呢, 策略模式总比直接依赖具体实现的方式要强得多.

3. 策略模式的优缺点

3.1 优点

  1. 符合开闭原则, 扩展性好, 因此在多人合作的时候, 代码易于维护(增加策略的时候, 只需要关注策略的具体实现)
  2. 可以在运行时切换策略.
  3. 可以将策略的具体实现和策略的使用这两部分代码隔离开来.

3.2 缺点

  1. 每种策略都对外暴露. (如果这也算缺点的话)

4. 参考

  1. 《设计模式》: refactoringguru.cn/design-patt...
  2. 刘丹冰, Easy设计模式: www.bilibili.com/video/BV1Eg...

5. 题外话

一点思考, 我之前学习的时候, 总是有一个地方不懂就钻牛角尖总想弄懂, 可是有些问题弄懂了面试也不问, 过了一段时间也忘记了, 对写更优雅的代码也没有帮助. 那么不如松弛一点, 尽力弄懂当前阶段能弄懂的即可, 一本武林秘籍, 给不同修为的人看, 他们能领悟的东西也是不同的吗.

杜绝"一个知识点只看一次, 一次看透"这个思想, 小猪乔治跟自己说.

相关推荐
da_vinci_x3 小时前
2D角色动画进阶:Spine网格变形与序列帧特效的混合工作流
游戏·设计模式·设计师·photoshop·spine·游戏策划·游戏美术
代码萌新知13 小时前
设计模式学习(五)装饰者模式、桥接模式、外观模式
java·学习·设计模式·桥接模式·装饰器模式·外观模式
charlie11451419116 小时前
理解C++20的革命特性——协程支持2:编写简单的协程调度器
c++·学习·算法·设计模式·c++20·协程·调度器
笨手笨脚の16 小时前
设计模式-适配器模式
设计模式·适配器模式·结构型设计模式
青草地溪水旁20 小时前
第五章:原型模式 - 克隆大法的大师
c++·设计模式·原型模式
1710orange1 天前
java设计模式:静态代理模式
java·设计模式·代理模式
我真的是大笨蛋1 天前
开闭原则详解(OCP)
java·设计模式·性能优化·开闭原则·设计规范
1710orange1 天前
java设计模式:动态代理
java·开发语言·设计模式
简小瑞1 天前
VSCode用它管理上千个服务:依赖注入从入门到实战
前端·设计模式
charlie1145141911 天前
精读C++20设计模式——结构型设计模式:外观模式
c++·学习·设计模式·c++20·外观模式