今天介绍一个常见的设计模式-策略模式,并基于一个简单的例子来讲解。
策略模式介绍
策略模式(Strategy Pattern)是一种行为型设计模式,它将一组算法封装成独立的对象,并使它们可以互相替换。这样做的好处是,可以在运行时动态地改变对象的行为,而不需要修改使用该对象的代码。
何时可以使用策略模式呢
我们在用GO编程的时候经常碰到多层控制语句,一层又一层,既不优雅,也不利于后续维护。比如下述这种:
if xxx {
// do something
} else if xxx {
// do something
} else if xxx {
// do something
else {
}
虽然按这种模式写起来简单快捷,但它也违背了面向对象的两个原则:
- 单一职责原则:多个控制语句,意味着拥有多种功能;
- 开闭原则:当要进行修改时,原有代码不可避免要被修改;
此时就可以采用策略模式来替换这类多层控制语句。
go 实现策略模式
go 语言该怎么实现策略模式呢?
在Go语言中,策略模式可以通过接口和函数来实现。首先,我们定义一个接口,该接口声明了算法执行的方法。然后,我们可以为每个具体的算法实现一个结构体,并实现接口中的方法。最后,我们可以在需要使用算法的地方,通过接口来调用具体的算法。
下面通过一个简单的例子来讲解策略模式, 现在有这样一个场景我们现在有2个数据表,这2个数据表拥有相同的字段,都可以根据 name 来查询某个数据,我们需要根据参数的不同来决定使用哪种表进行查询, 在没有使用策略模式时, 我们往往使用大量的if来实现这个操作。 接下来由我来介绍策略模式来实现相同的操作。
先定义查询操作的接口:
type DataStrategy interface {
Query(name string)
}
定义2张表的查询struct,并实现DataStrategy接口:
// table1 通过table1 来查询
type table1 struct{}
func (s *table1) Query(name string) {
fmt.Println("table1 query")
}
// table2
type table2 struct{}
func (s *table2) Query(name string) {
fmt.Println("table2 query")
}
再定义 Data 对象用来执行不同的策略:
type Data struct {
impl DataStrategy
}
func (r *Data) SetTable(i DataStrategy) {
r.impl = i
}
func (r *Data) Query(name string) {
r.impl.Query(name)
}
运行代码:
table1 query
table2 query
小结
策略模式是一种非常有用的设计模式,它可以在不修改现有代码的情况下,动态地改变算法或行为。在Go语言中,我们可以通过接口和函数来实现策略模式。通过合理地应用策略模式,我们可以使代码更加灵活、可扩展,并提高代码的可维护性。