美文网首页区块链编程Go
gof23行为类模式(golang版)

gof23行为类模式(golang版)

作者: 五月花号区块链联盟 | 来源:发表于2018-12-08 23:20 被阅读2次

    命令模式

    image

    命令模式是一个高内聚的模式,其定义:将一个请求封装成一个对象,从而让你使用不同的请求客户端参数化,对请求排除或者记录请求日志,可以提供命令的撤销和恢复功能。

    命令模式包含如下角色:

    • Command: 抽象命令类
      需要执行的所有命令得出在这里声明。
    • ConcreteCommand: 具体命令类
      负责实现在Command角色中定义的接口
    • Invoker: 调用者
      开始执行命令的角色,它会调用在Command角色中定义的接口。
    • Receiver: 接收者
      该角色就是干活的角色,命令传递到这里是应该被执行的

    命令模式的优点

    • 类间解耦
      调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只须调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行

    • 可扩展性
      Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合

    命令模式的缺点

    偏偏模式的缺点就是膨胀,如果有N个命令,问题就出来了,Command的子类会有N个。

    代码实现

    package main
    
    import (
        "fmt"
    )
    
    /**
    Command: 抽象命令类
    ConcreteCommand: 具体命令类
    Invoker: 调用者
    Receiver: 接收者
     */
    
    // receiver
    type TV struct {
    }
    
    func (p TV) Open() {
        fmt.Println("play...")
    }
    
    func (p TV) Close() {
        fmt.Println("stop...")
    }
    
    //command
    type Command interface {
        Press()
    }
    
    //ConcreteCommand
    type OpenCommand struct {
        tv TV
    }
    
    func (p OpenCommand) Press() {
        p.tv.Open()
    }
    
    //ConcreteCommand
    type CloseCommand struct {
        tv TV
    }
    
    
    func (p CloseCommand) Press() {
        p.tv.Close()
    }
    
    //invoker
    type Invoke struct {
        cmd Command
    
    }
    
    func (p *Invoke) SetCommand(cmd Command) {
        p.cmd = cmd
    }
    
    func (p *Invoke) Do() {
        p.cmd.Press()
    }
    
    type OpenCloseCommand struct {
        index int
        cmds []Command
    }
    
    
    func NewOpenCLoseCommand() *OpenCloseCommand {
        openCLose := &OpenCloseCommand{}
        openCLose.cmds = make([]Command, 2)
        return openCLose
    }
    
    func (p *OpenCloseCommand) AddCommand(cmd Command) {
        p.cmds[p.index] = cmd
        p.index++
    }
    
    func (p *OpenCloseCommand) Press() {
        for _, item := range p.cmds {
            item.Press()
        }
    }
    
    func main() {
        //单一命令
        tv := TV{}
        openCommand := OpenCommand{tv}
        invoker := Invoke{openCommand}
        invoker.Do()
    
        closeCommand := CloseCommand{tv}
        invoker.SetCommand(closeCommand)
        invoker.Do()
    
        //复合命令
        fmt.Println("############复合命令###############")
        openClose := NewOpenCLoseCommand()
        openClose.AddCommand(openCommand)
        openClose.AddCommand(closeCommand)
    
        invoker.SetCommand(openClose)
        invoker.Do()
    }
    

    中介者模式

    image
    image

    中介者模式的定义为:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

    中介者模式化多对多依赖为一对多依赖。

    中介者模式由以下部分组成

    • Mediator: 抽象中介者
      抽象中介者角色定义统一的接口,用于各同事角色之间的通信
    • ConcreteMediator: 具体中介者
      具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色
    • Colleague: 抽象同事类
      每一个同事角色都知道中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。
    • ConcreteColleague: 具体同事类
      每个同事类的行为分为两种:一种是再带本身的行为,比如改变对象本身的状态,处理自己的行为等,这种行为叫做自发行为,与其他的同事类或中介者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法。

    中介者模式的优点

    减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,同时也降低了类间的耦合
    

    中介者模式的缺点

    中介者会膨胀得很大,而且逻辑复杂

    代码实现

    package behavior
    
    import "fmt"
    
    /**
    Mediator: 抽象中介者
    ConcreteMediator: 具体中介者
    Colleague: 抽象同事类
    ConcreteColleague: 具体同事类
     */
    
    //mediator 及 ConcreteMediator
    type UnitedNations interface {
        ForwardMessage(message string, country Country)
    }
    
    type UnitedNationsSecurityCouncil struct {
        USA
        Iraq
    }
    
    func (unsc UnitedNationsSecurityCouncil) ForwardMessage(message string, country Country) {
        switch country.(type) {
        case USA:
            unsc.Iraq.GetMessage(message)
        case Iraq:
            unsc.USA.GetMessage(message)
        default:
            fmt.Printf("The country is not a member of UNSC")
        }
    }
    
    type Country interface {
        SendMessage(message string)
        GetMessage(message string)
    }
    
    //Colleague以及ConcreteColleague类
    type USA struct {
        UnitedNations
    }
    
    func (usa USA) SendMessage(message string) {
        usa.UnitedNations.ForwardMessage(message, usa)
    }
    
    func (usa USA) GetMessage(message string) {
        fmt.Printf("美国收到对方消息: %s\n", message)
    }
    
    type Iraq struct {
        UnitedNations
    }
    
    func (iraq Iraq) SendMessage(message string) {
        iraq.UnitedNations.ForwardMessage(message, iraq)
    }
    
    func (iraq Iraq) GetMessage(message string) {
        fmt.Printf("伊拉克收到对方消息: %s\n", message)
    }
    
    

    client

    package main
    
    import "gof23/behavior"
    
    func main() {
        tMediator := behavior.UnitedNationsSecurityCouncil{}
        usa := behavior.USA{tMediator}
    
        iraq := behavior.Iraq{tMediator}
    
        tMediator.USA = usa
        tMediator.Iraq = iraq
    
        usa.SendMessage("停止大规模杀伤性武器的研发,否则发动战争")
        iraq.SendMessage("我们没有研发大规模杀伤性武器,也不怕战争")
    }
    
    

    观察者模式

    观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

    观察者模式包含如下角色:

    • Subject: 目标
      表示观察对象
    • ConcreteSubject: 具体目标
      表示具体的被观察对象。
    • Observer: 观察者
      负责接收来自Subject角色的状态变化通知
    • ConcreteObserver: 具体观察者
      表示具体的Observer
    image

    观察者模式的优点

    • 观察者和被观察者之间是抽象耦合
      如此设计,则不管是增加观察者还是被观察者都非常容易扩展
    • 建立一套触发机制
      根据单一职责原则每个类的职责是单一的,那么怎么把各个单一的职责串联成真实世界的复杂的逻辑关系呢?观察者模式可以完美地实现这里的链条形式

    观察者模式的缺点

    观察者模式需要考虑一下开发效率和运行效率问题

    代码实现

    package observer
    
    import "fmt"
    
     //抽象观察者
    type IObserver interface {
        Notify() //当被观察对象有理性的时候,触发观察者的Notify()方法
    }
    
    //具体观察者
    type Observer struct {
    }
    
    func (o *Observer) Notify() {
        fmt.Println("已经触发了观察者")
    }
    
    package observer
    
    //抽象被观察者
    type ISubject interface {
        AddObservers(observers ...IObserver) //添加观察者
        NotifyObservers() //通知观察者
    }
    
    //具体被观察者
    type Subject struct {
        observers []IObserver
    }
    
    func (s *Subject) AddObservers(observer ...IObserver) {
        s.observers = append(s.observers, observer...)
    }
    
    func (s *Subject) NotifyObservers() {
    
        for k := range s.observers {
            s.observers[k].Notify() //触发观察者
        }
    }
    
    package main
    
    import "gof23/behavior/observer"
    
    func main() {
        s := new(observer.Subject)
        o := new(observer.Observer)
    
        s.AddObservers(o)
    
        s.NotifyObservers()
    }
    

    状态模式

    状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。

    状态模式包含如下角色:

    • Context: 环境类
      定义客户端需要的接口,并且负责具体状态的切换

    • State: 抽象状态类
      接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换

    • ConcreteState: 具体状态类
      每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。

    image

    状态模式的优点

    封装了转换规则。
    枚举可能的状态,在枚举状态之前需要确定状态种类。
    将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
    允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
    可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

    状态模式的缺点

    状态模式的使用必然会增加系统类和对象的个数。
    状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
    状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

    代码实现

    package state
    
    import "fmt"
    
    //抽象状态角色
    type State interface {
        NextState() State
        Update()
    }
    
    //具体状态角色
    type GameStartState struct {
    }
    
    type GameRunState struct {
    }
    
    type GameEndState struct {
    }
    
    func (this *GameStartState) NextState() State {
        fmt.Println("Start next...")
        return new(GameRunState)
    }
    
    func (this *GameStartState) Update() {
        fmt.Println("Game start...")
    }
    
    func (this *GameRunState) NextState() State {
        fmt.Println("Run next...")
        return new(GameEndState)
    }
    
    func (this *GameRunState) Update() {
        fmt.Println("Game run...")
    }
    
    func (this *GameEndState) NextState() State {
        fmt.Println("End next...")
        return new(GameStartState)
    }
    
    func (this *GameEndState) Update() {
        fmt.Println("End")
    }
    

    client

    package main
    
    import (
        "gof23/behavior/state"
        "time"
    )
    
    //context角色
    func stateMechine(state state.State, ch chan int)  {
        for  {
            select {
                case i := <-ch :
                    if i == 1 {
                        state.Update()
                        state = state.NextState()
                    } else if i == 0 {
                        return
                    }
                default:
    
            }
        }
    }
    
    func main() {
        st := new(state.GameStartState)
        ch := make(chan int)
    
        go stateMechine(st, ch)
        time.Sleep(time.Microsecond * 3)
        ch <- 1
        time.Sleep(time.Microsecond * 3)
        ch <- 1
        time.Sleep(time.Microsecond * 3)
        ch <- 1
        time.Sleep(time.Microsecond * 3)
        ch <- 0
    }
    

    http://www.ituring.com.cn/article/200362

    策略模式

    策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。

    策略模式包含如下角色:

    • Context: 环境类
    • Strategy: 抽象策略类
    • ConcreteStrategy: 具体策略类
    image

    策略模式的优点

    策略模式的优点

    策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
    策略模式提供了管理相关的算法族的办法。
    策略模式提供了可以替换继承关系的办法。
    使用策略模式可以避免使用多重条件转移语句。

    策略模式的缺点

    策略模式的缺点

    客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
    策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

    代码实现

    package strategy
    
    //抽象策略角色
    type cashStrategy interface {
        AcceptCash(float64) float64
    }
    
    //具体策略角色
    type cashNormal struct {
    }
    
    func (normal *cashNormal) AcceptCash(money float64) float64 {
        return money
    }
    
    type cashRebate struct {
        moneyRebate float64
    }
    
    func (rebate *cashRebate) AcceptCash(money float64) float64 {
        return money * rebate.moneyRebate
    }
    
    type cashReturn struct {
        moneyCondition float64
        moneyReturn float64
    }
    
    func (returned *cashReturn) AcceptCash(money float64) float64 {
        if money >= returned.moneyCondition {
            return money - float64(int(money / returned.moneyCondition)) * returned.moneyReturn
        } else {
            return money
        }
    }
    
    // context角色
    type CashContext struct {
        Stratege cashStrategy
    }
    
    func NewCashContext(cashType string) *CashContext {
        c := new(CashContext)
    
        switch cashType {
        case "打八折":
            c.Stratege = &cashRebate{0.8}
        case "满300返100":
            c.Stratege = &cashReturn{300, 100}
        case "正常收费":
            c.Stratege = &cashNormal{}
        }
        return c
    }
    

    client

    package main
    
    import (
        "gof23/behavior/strategy"
        "fmt"
    )
    
    func main() {
        var total float64 = 0
    
        context := strategy.NewCashContext("满300返100")
        total += context.Stratege.AcceptCash(1 * 10000)
    
        context = strategy.NewCashContext("正常收费")
        total += context.Stratege.AcceptCash(1 * 10000)
    
        context = strategy.NewCashContext("打八折")
        total += context.Stratege.AcceptCash(1 * 10000)
        fmt.Println(total)
    }
    

    相关文章

      网友评论

        本文标题:gof23行为类模式(golang版)

        本文链接:https://www.haomeiwen.com/subject/qofqhqtx.html