设计模式-策略模式(Go语言描写叙述)
2017-06-23 18:38
375 查看
好久没有更新博客了。近期也是在忙着充电,今天这篇博客開始,我们来了解一下设计模式。
设计模式/软件设计模式(Design pattern)是一套被重复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更easy被他人理解、保证代码可靠性。
恩。大概的意思就是在撸码界由码神们总结的、能够解决软件设计中重复出现的问题的、由大多数人不论什么的设计方式,也能够说是一种编码规则。
初始编码我们总是依照自己的套路来写代码。等项目的代码量庞大了,需求又要改了,突然发现尼玛这个改起来好麻烦,好多文件要动,为了适合新的需求改动这个文件可能会对其它的业务逻辑产生影响,改动这个文件会不会引入bug?一系列的问题摆在了我们眼前,头疼、迷茫,有木有一种又一次写一遍的冲动?好了,假如你遇到了这样的情况。设计模式可能会解救你一部分。
但。对于设计模式还有非常多人很多其它沉迷于设计模式中,每写几行代码,都要考虑考虑-这里是不是须要个啥模式! 记住。模式是为了方便我们解决这个问题而总结出来的一套编码规则。并非我们不用设计模式代码的扩展性就一定差。选择使用模式还是要谨慎,大多数情况下还是要依靠需求的情景来考虑需不须要这样的模式,在决定使用之前一定要考虑好为什么要用这样的模式。
定义一系列算法,将每个算法封装起来。并让它们能够相互替换。策略模式让算法独立于使用它的客户而变化。
恩。这个定义看起来还是能够的,不像一些定义非得整的人看不懂才叫定义,随便还算好理解。只是我们还是要引入一个结构图来更加清晰的认识它。
![](http://img.blog.csdn.net/20160122234552935)
看到这个结构图,大概可能或许会恍然大悟了。这不就是让我们针对接口编程了。恩是的,差点儿相同全部的设计模式都是要遵循针对接口编程这个规则,并且我们细致想一下,这里面还体现出了对扩展开发,对改动关闭(开闭原则) ,假设我们要添加一些规则,全然不用改动主业务流程。仅仅须要添加几个策略就ok,当然了。这些策略要遵循我们的接口规范。
首先,我们看到的将会是策略接口和一系列的策略,这些策略不要依赖高层模块的实现。
非常easy的一个接口,定义了一个方法
接下来,我们来看一个我们实现的策略,
为什么要拿除法作为代表呢?由于除法特殊嘛,被除数不能为0,其它的加减乘基本都是一行代码搞定,除法我们须要推断被除数是否为0,假设是0则直接抛出异常。
ok,主要的策略定义好了。我们还须要一个工厂方法,依据不用的type来返回不同的策略。这个type我们准备从命令好输入。
这个工厂方法会依据不用的类型来返回不同的策略实现。当然。哪天我们须要新增新的策略,我们仅仅须要在这个函数中添加相应的类型推断就ok。
如今策略貌似已经完毕了。接下来我们来看看主流程代码。一个Computer,
这个Computer中有三个參数,
貌似一切准备就绪,我们就来编写main的代码吧。
首先我们要从命令行读取要使用的策略类型和两个操作数。在main函数中,我们初始化
就是这么简单。如今我们在命令行定位到
go build main.go
继续运行命令
main -type d -num1 4 -num2 2
来尝试一下使用加法策略操作4和2这两个数,来看看结果怎样,
![](http://img.blog.csdn.net/20160122234625592)
结果非常正确。换一个策略试试。来个乘法吧,运行命令
main -type m -num1 4 -num2 2
![](http://img.blog.csdn.net/20160122234636654)
结果也是正确的。
一定要记得哦。我们的代码要往对扩展开发,对改动关闭这条设计原则上努力!
最后是本文的实例代码下载:http://download.csdn.net/detail/qibin0506/9415084
设计模式
那什么是设计模式呢?首先来看看我从百科上copy下来的概念吧。设计模式/软件设计模式(Design pattern)是一套被重复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更easy被他人理解、保证代码可靠性。
恩。大概的意思就是在撸码界由码神们总结的、能够解决软件设计中重复出现的问题的、由大多数人不论什么的设计方式,也能够说是一种编码规则。
初始编码我们总是依照自己的套路来写代码。等项目的代码量庞大了,需求又要改了,突然发现尼玛这个改起来好麻烦,好多文件要动,为了适合新的需求改动这个文件可能会对其它的业务逻辑产生影响,改动这个文件会不会引入bug?一系列的问题摆在了我们眼前,头疼、迷茫,有木有一种又一次写一遍的冲动?好了,假如你遇到了这样的情况。设计模式可能会解救你一部分。
但。对于设计模式还有非常多人很多其它沉迷于设计模式中,每写几行代码,都要考虑考虑-这里是不是须要个啥模式! 记住。模式是为了方便我们解决这个问题而总结出来的一套编码规则。并非我们不用设计模式代码的扩展性就一定差。选择使用模式还是要谨慎,大多数情况下还是要依靠需求的情景来考虑需不须要这样的模式,在决定使用之前一定要考虑好为什么要用这样的模式。
策略模式
好了,扯了这么多蛋,以下開始进入主题,进来我们首先来介绍一下策略模式。首先来看一下定义,定义一系列算法,将每个算法封装起来。并让它们能够相互替换。策略模式让算法独立于使用它的客户而变化。
恩。这个定义看起来还是能够的,不像一些定义非得整的人看不懂才叫定义,随便还算好理解。只是我们还是要引入一个结构图来更加清晰的认识它。
看到这个结构图,大概可能或许会恍然大悟了。这不就是让我们针对接口编程了。恩是的,差点儿相同全部的设计模式都是要遵循针对接口编程这个规则,并且我们细致想一下,这里面还体现出了对扩展开发,对改动关闭(开闭原则) ,假设我们要添加一些规则,全然不用改动主业务流程。仅仅须要添加几个策略就ok,当然了。这些策略要遵循我们的接口规范。
代码实现
以下我们就開始以代码的形式来展示一下策略模式吧,代码非常easy,我们用一个加减乘除法来模拟。首先,我们看到的将会是策略接口和一系列的策略,这些策略不要依赖高层模块的实现。
package strategy /** * 策略接口 */ type Strategier interface { Compute(num1, num2 int) int }
非常easy的一个接口,定义了一个方法
Compute。接受两个參数。返回一个int类型的值,非常easy理解。我们要实现的策略将会将两个參数的计算值返回。
接下来,我们来看一个我们实现的策略,
package strategy import "fmt" type Division struct {} func (p Division) Compute(num1, num2 int) int { defer func() { if f := recover(); f != nil { fmt.Println(f) return } }() if num2 == 0 { panic("num2 must not be 0!") } return num1 / num2 }
为什么要拿除法作为代表呢?由于除法特殊嘛,被除数不能为0,其它的加减乘基本都是一行代码搞定,除法我们须要推断被除数是否为0,假设是0则直接抛出异常。
ok,主要的策略定义好了。我们还须要一个工厂方法,依据不用的type来返回不同的策略。这个type我们准备从命令好输入。
func NewStrategy(t string) (res Strategier) { switch t { case "s": // 减法 res = Subtraction{} case "m": // 乘法 res = Multiplication{} case "d": // 除法 res = Division{} case "a": // 加法 fallthrough default: res = Addition{} } return }
这个工厂方法会依据不用的类型来返回不同的策略实现。当然。哪天我们须要新增新的策略,我们仅仅须要在这个函数中添加相应的类型推断就ok。
如今策略貌似已经完毕了。接下来我们来看看主流程代码。一个Computer,
package compute import ( "fmt" s "../strategy" ) type Computer struct { Num1, Num2 int strate s.Strategier } func (p *Computer) SetStrategy(strate s.Strategier) { p.strate = strate } func (p Computer) Do() int { defer func() { if f := recover(); f != nil { fmt.Println(f) } }() if p.strate == nil { panic("Strategier is null") } return p.strate.Compute(p.Num1, p.Num2) }
这个Computer中有三个參数,
Num1和
Num2当然是我们要操作的数了。strate是我们要设置的策略,可能是上面介绍的
Division,也有可能是其它的,在main函数中我们会调用
SetStrategy方法来设置要使用的策略,
Do方法会运行运算,最后返回运算的结果,能够看到在
Do中我们将计算的功能托付给了
Strategier。
貌似一切准备就绪,我们就来编写main的代码吧。
package main import ( "fmt" "flag" c "./computer" s "./strategy" ) var stra *string = flag.String("type", "a", "input the strategy") var num1 *int = flag.Int("num1", 1, "input num1") var num2 *int = flag.Int("num2", 1, "input num2") func init() { flag.Parse() } func main() { com := c.Computer{Num1: *num1, Num2: *num2} strate := s.NewStrategy(*stra) com.SetStrategy(strate) fmt.Println(com.Do()) }
首先我们要从命令行读取要使用的策略类型和两个操作数。在main函数中,我们初始化
Computer这个结构体,并将输入的操作数赋值给
Computer的
Num1和
Num2,接下来我们依据策略类型通过调用
NewStrategy函数来获取一个策略,并调用
Computer的
SetStrategy方法给
Computer设置上面获取到的策略。最后运行
Do方法计算结果,最后打印。
就是这么简单。如今我们在命令行定位到
main.go所在的文件夹。并运行一下命令来编译文件
go build main.go
继续运行命令
main -type d -num1 4 -num2 2
来尝试一下使用加法策略操作4和2这两个数,来看看结果怎样,
结果非常正确。换一个策略试试。来个乘法吧,运行命令
main -type m -num1 4 -num2 2
结果也是正确的。
总结
策略模式还是算比較easy理解的。策略模式的核心就是将easy变动的代码从主逻辑中分离出来,通过一个接口来规范它们的形式。在主逻辑中将任务托付给策略。这样做既降低了我们对主逻辑代码改动的可能性,也添加了系统的可扩展性。一定要记得哦。我们的代码要往对扩展开发,对改动关闭这条设计原则上努力!
最后是本文的实例代码下载:http://download.csdn.net/detail/qibin0506/9415084
相关文章推荐
- 设计模式-适配器模式(Go语言描写叙述)
- go语言实现设计模式(一):策略模式
- [设计模式]-策略模式-JAVA语言
- go语言实现设计模式(三):模版模式
- 策略设计模式与c语言中的函数指针
- Go语言设计模式实践:迭代器(Iterator)
- 超赞的GO语言设计模式和成例集锦
- Go---设计模式(策略模式)
- Go语言设计模式实践:组合(Composite)
- Go语言设计模式实践:迭代器(Iterator)
- go语言: 设计模式-代理模式(Go语言描述)
- 设计模式之Strategy(策略)
- 设计模式c#语言描述——建造者模式、适配器模式、合成(Composite)模式
- 设计模式之策略模式探讨初步[引]
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
- 设计模式随笔系列:鸭子-策略模式(Strategy)[原]
- 委托,语言级别的设计模式
- 设计模式之策略模式在设计一群鸭子中的应用
- 设计模式与泡mm的关系之strategy策略模式及再思考