zoukankan      html  css  js  c++  java
  • 设计模式-策略模式(Go语言描写叙述)

    好久没有更新博客了。近期也是在忙着充电,今天这篇博客開始,我们来了解一下设计模式。

    设计模式

    那什么是设计模式呢?首先来看看我从百科上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中有三个參数,Num1Num2当然是我们要操作的数了。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这个结构体,并将输入的操作数赋值给ComputerNum1Num2,接下来我们依据策略类型通过调用NewStrategy函数来获取一个策略,并调用ComputerSetStrategy方法给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

  • 相关阅读:
    Building a Space Station POJ
    Networking POJ
    POJ 1251 Jungle Roads
    CodeForces
    CodeForces
    kuangbin专题 专题一 简单搜索 POJ 1426 Find The Multiple
    The Preliminary Contest for ICPC Asia Shenyang 2019 F. Honk's pool
    The Preliminary Contest for ICPC Asia Shenyang 2019 H. Texas hold'em Poker
    The Preliminary Contest for ICPC Asia Xuzhou 2019 E. XKC's basketball team
    robotparser (File Formats) – Python 中文开发手册
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7071305.html
Copyright © 2011-2022 走看看