策略模式(Strategy Pattern)
定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换。
策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。
策略模式是一种对象行为模式。
策略模式中的 3 个角色:
策略模式中,对环境类的理解十分重要,环境类是需要使用算法的类,环境类根据具体的环境上下文使用不同的算法。
环境类中维持一个对抽象策略的引用,在具体环境中使用不同的策略算法。
在客户端代码中表现为向环境类中注入一个具体策略对象。
条条大路通罗马,实现目的的途径不止一条,可以根据实际情况选择合适的途径。
当处理一个业务时,有多种处理方式,并且需要在运行时决定使用哪一种具体实现时,就可以使用策略模式。
策略模式基本上是实际开发过程中最常用、最实用的设计模式了。
策略模式能有效解决部分场景中大量的 if ... else 代码,提升代码的可读性和扩展性。
案例:
下面就已多云管理平台 CMP 中,最常见的创建不同虚拟化平台的虚拟机为例,对比下使用与不使用策略设计代码的区别。
package main
import "fmt"
type VirtualMachine struct {
Name string
Type string // OpenStack | VMware | Aliyun
}
func (vm VirtualMachine) create() {
if vm.Type == "OpenStack" {
fmt.Println("do some before create OpenStack VirtualMachine")
fmt.Println("call OpenStack API create VirtualMachine")
fmt.Println()
} else if vm.Type == "VMware" {
fmt.Println("do some before create VMware VirtualMachine")
fmt.Println("call VMware API create VirtualMachine")
fmt.Println()
} else if vm.Type == "Aliyun" {
fmt.Println("do some before create Aliyun VirtualMachine")
fmt.Println("call Aliyun API create VirtualMachine")
fmt.Println()
}
}
func main() {
var virtualMachineType = "OpenStack"
vm := VirtualMachine{Name: "An Aliyun VirtualMachine", Type: virtualMachineType}
vm.create()
}
虽然,这种方式创建不同的虚拟机不需要修改创建的源码,只需要修改新建结构体时 type 参数。
但是,这种方式还是有一些缺陷。
package main
import "fmt"
type VirtualMachineOperator interface {
create()
}
type OpenStackVirtualMachine struct {
// VirtualMachine 通用属性
vm VirtualMachine
// OpenStack VirtualMachine 个性化属性
OpenStackFiled string
}
func (vm OpenStackVirtualMachine) create() {
fmt.Println("do some before create OpenStack VirtualMachine")
fmt.Println("call OpenStack API create VirtualMachine")
fmt.Println()
}
type VMwareVirtualMachine struct {
vm VirtualMachine
VMwareFiled string
}
func (vm VMwareVirtualMachine) create() {
fmt.Println("do some before create VMware VirtualMachine")
fmt.Println("call VMware API create VirtualMachine")
fmt.Println()
}
type AliyunVirtualMachine struct {
vm VirtualMachine
AliyunFiled string
}
func (vm AliyunVirtualMachine) create() {
fmt.Println("do some before create Aliyun VirtualMachine")
fmt.Println("call Aliyun API create VirtualMachine")
fmt.Println()
}
type VirtualMachine struct {
Name string
Type string // OpenStack | VMware | Aliyun
VMOperator VirtualMachineOperator
}
func (vm VirtualMachine) create() {
fmt.Println("do some before create VirtualMachine")
vm.VMOperator.create()
}
func main() {
var virtualMachineType = "OpenStack"
vm := VirtualMachine{Name: "An OpenStack VirtualMachine", Type: virtualMachineType, VMOperator: OpenStackVirtualMachine{}}
vm.create()
}
定义独立的类来封装不同的策略算法,每个类封装一种具体的策略算法。
为了保证这些不同策略算使用时的一致性,通常会提供一个抽象的策略接口来做规则的定义,每种算法则对应一个具体的策略类。
这种方式给 VirtualMachine 定义了统一的操作接口 VirtualMachineOperator,每种类型 VirtualMachine 有自己的结构体和接口方法的实现。
每种类型 VirtualMachine 结构体可以定义自己特有的属性,实现自己的操作方法。
使用方客户端(环境类)只需要维护好 VirtualMachine Entity 和 VirtualMachine Operator 之间的引用关系,即可创建对应类型的虚拟机。
OpenStackVirtualMachine、VMwareVirtualMachine、AliyunVirtualMachine 代码可以分文件独立编写,这样阅读起来也更加简洁。
策略模式的核心是将算法的定义与使用分开,也就是将算法的行为和环境分开。
将算法的定义放在专门的策略类中,每个策略类封装了一个种实现算法。
使用算法的环境类根据上下文使用对应的策略类,符合依赖倒转原则。
在出现新的算法时,只需要增加一个新的实现了抽象策略类的具体策略类即可。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。