请选择 进入手机版 | 继续访问电脑版

策略模式【Go实现】

[复制链接]
黎平 发表于 2020-12-31 20:24:40 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
Go实现设计模式——战略模式


战略模式

在生活中,我们常常会处于需要举行某种战略选择的场景——比方,购物节有差别的打折方案供我们选择、出行旅游也有多种交通方式等。一种战略便是一种“方案”,同一类战略都具有相同类型的输入和输出。在步调设计过程中,我们也会遇到需要举行战略选择的情况,比如棋盘游戏算法设计中,针对差别的难度选用差别类型的算法等。那么如何来实现战略的机动变更呢?
战略模式通过界说算法族的方式,分别封装差别的算法,让它们之间可以相互替换,此模式让算法的变革独立于使用算法的客户。
模拟鸭子应用(DuckSimulation)

初始项目

我们来实现一个鸭子模拟的应用,鸭子会游泳、会呱呱叫。依据面向对象的设计方法,我们暂时设计出了下面的产物。

  1. @startuml Initial Duck Class Diagramabstract class Duck{    +Swin()    +Quack()    {abstract} +Display()}class MallarDuck extends Duck{    +Display()}class RedHeadDuck extends Duck{    +Display()}@enduml
复制代码
新的需求——让鸭子飞起来

现在我们需要给鸭子们添加新的功能,让鸭子飞起来!
最简单的方法便是给父类Duck添加Fly方法。

  1. @startuml Duck Class With Flyabstract class Duck{+Swin()+Quack()+Fly(){abstract} +Display()}class MallarDuck extends Duck{+Display()}class RedHeadDuck extends Duck{+Display()}@enduml
复制代码
很好,至少目前看来我们实现了这个需求,而且只增加了少量的代码,同时我们没有额外修改已经存在的代码,干得美丽! 我们遇到了新的问题——一只会飞的橡皮鸭

我们又遇到了问题——当我们增加了一只橡皮鸭(RubberDuck)的时候,它飞了起来!我们可不能让橡皮鸭飞起来。

  1. @startuml Rubber Duck Can Flyabstract class Duck{    +Swin()    +Quack()    +Fly()    {abstract} +Display()}class MallarDuck extends Duck{    +Display() }class RedHeadDuck extends Duck{    +Display()}class RubberDuck extends Duck{    +Quack()    +Display()}@enduml
复制代码
  1. aRubberDuck := &RubberDuck{}aRubberDuck.Fly() // it works!
复制代码
管理方案一

使用继续的特性,我们实验让橡皮鸭重写(override)Duck的Fly方法,来让它老诚实实呆在地上。

  1. @startuml Rubber Duck Cannot Flyabstract class Duck{    +Swin()    +Quack()    +Fly()    {abstract} +Display()}class MallarDuck extends Duck{    +Display() }class RedHeadDuck extends Duck{    +Display()}class RubberDuck extends Duck{    +Quack()    +Display()    +Fly()}@enduml
复制代码
橡皮鸭总算是不会自己飞起来了!
但是仔细想想,如果我们有新的不会飞的小鸭子们,大家都要重写一遍Fly方法吗?会飞的姿势五花八门,不会飞的灵魂千篇一律。显着大家都是一样的不会飞!这样重复的代码可太多了。况且调用一个“没有用”的方法可真让人摸不着头脑。
管理方案二

使用接口,让需要飞的鸭子们各自实现自己的飞行姿势!

  1. @startuml Ducks With Fly Interfaceinterface Flyable{    Fly()}abstract class Duck{    +Swin()    +Quack()    {abstract} +Display()}class MallarDuck extends Duck implements Flyable {    +Display()}class RedHeadDuck extends Duck implements Flyable{    +Display()}class RubberDuck extends Duck{    +Quack()    +Display()}@enduml
复制代码
Oh! 我们制止了重写大量Fly方法——现在只需要大量的实现……
给我们的小鸭子装上飞行插件

两种管理方案都不太完美。我的意思是,既然有许多类不需要Fly,同时,剩下的类里面,有的需要同样形式的Fly,有的又需要差别形式的Fly,那我们何不把Fly抽象出来呢?不是让它作为一个低级的方法,而是把它酿成一个emmm插件?这样我就可以方便定制类的行为了!不是吗?

  1. @startuml Duck With Fly Strategyinterface FlyBehavior{    Fly()}abstract class Duck{    -FlyBehavior doFly    +Swin()    +Quack()    +Fly()    +setFlyBehavior(Flyable)    {abstract} +Display()}Duck::doFly -l-> FlyBehaviorclass MallarDuck extends Duck {    +Display()}class RedHeadDuck extends Duck {    +Display()}class RubberDuck extends Duck {    +Quack()    +Display()}class NoFly implements FlyBehavior{    +Fly()}class FlyWithWings implements FlyBehavior{    +Fly()}@enduml
复制代码
这样我们就可以方便定制我们的飞行方式了!而且不需要为了飞行方式的变更而修改小鸭子们了!换言之,我们将鸭子的飞行行为的详细实现托管给了FlyBehavior,我们乐成的分开的会变革和不会变革的部门。现在我们甚至可以在步调运行过程中对鸭子们的飞行体现举行设置!
  1. type FlyBehavior interface {        Fly()}// NoFly 无需飞行type NoFly struct {}func (f *NoFly) Fly() {        fmt.Println("不消飞~")}type Duck struct {        doFly FlyBehavior}func (duck *Duck) Fly() {        // 将飞行行为托管给飞行战略        duck.doFly.Fly()}func (duck *Duck) SetFlyBehavior(flyBehavior FlyBehavior) {        duck.doFly = flyBehavior}
复制代码
  1. aMallarDuck := ducksim.MallarDuck{}aMallarDuck.SetFlyBehavior(&ducksim.FlyWithWings{})aMallarDuck.Swim()aMallarDuck.Fly()aRubberDuck := ducksim.RubberDuck{}aRubberDuck.SetFlyBehavior(&ducksim.NoFly{})aRubberDuck.Quack()aRubberDuck.Fly()
复制代码
步调输出(go build main.go)
  1. Duck Swiming用翅膀飞!吱吱不消飞~
复制代码
总结

通过战略模式,我们将飞行这一行为从方法提升到了类。将飞行的详细行为托管给了FlyBehavior接口,这样,我们就可以专心控制鸭子和飞行这两件事了。团结战略模式的界说——通过界说算法族的方式,分别封装差别的算法,让它们之间可以相互替换。在这里,FlyBehavior便是我们界说的算法族。
战略模式很好的体现了“面向接口编程”,制止类和一个详细实现高度耦合。同时也符合多用组合少用继续的设计原则。
源码

来源:https://blog.csdn.net/JunhuanPeng/article/details/111991652
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )