美文网首页程序员设计模式
手撸golang 行为型设计模式 委派模式

手撸golang 行为型设计模式 委派模式

作者: 老罗话编程 | 来源:发表于2021-02-05 09:30 被阅读0次

    手撸golang 行为型设计模式 委派模式

    缘起

    最近复习设计模式
    拜读谭勇德的<<设计模式就该这样学>>
    本系列笔记拟采用golang练习之

    委派模式

    委派模式(Delegate Pattern)又叫作委托模式,基本作用就是负责任务的调用和分配,是一种特殊的静态代理模式,可以理解为全权代理模式,但是代理模式注重过程,而委派模式注重结果。
    委派模式有3个参与角色。
    (1)抽象任务角色(ITask):定义一个抽象接口,它有若干实现类。
    (2)委派者角色(Delegate):负责在各个具体角色实例之间做出决策,判断并调用具体实现的方法。
    (3)具体任务角色(Concrete):真正执行任务的角色。
    _

    场景

    • 某消息处理系统, 需要处理客户端请求的各种消息
    • 为方便后续扩展统一的消息日志/审计/权限/安全等功能, 根据委派模式, 所有消息由全局调度器统一调度
    • 调度器根据消息的类型, 委派给具体的消息处理器

    设计

    • IMsg: 定义消息接口
    • BaseMsg: 消息的基类, 实现IMsg接口
    • EchoMsg: 表示原样返回的消息, 用于PING/PONG心跳. 继承自BaseMsg
    • TimeMsg: 表示获取服务器时间的消息. 继承自BaseMsg
    • IMsgHandler: 消息处理器接口. 调度器和具体消息处理器, 均需要实现此接口.
    • tMsgDispatchDelegate: 全局消息调度器, 是所有客户端消息的统一入口. 用于注册消息处理器, 按类型分发消息.
    • tEchoMsgHandler: 专门处理EchoMsg消息的处理器. 实现IMsgHandler接口.
    • tTimeMsgHandler: 专门处理TimeMsg消息的处理器, 实现IMsgHandler接口.

    单元测试

    delegate_pattern_test.go

    package behavioral_patterns_test
    
    import (
        "fmt"
        "learning/gooop/behavioral_patterns/delegate"
        "testing"
    )
    
    func Test_DelegatePattern(t *testing.T) {
        dispatcher := delegate.GlobalMsgDispatcher
        vEchoMsg := delegate.NewEchoMsg("msg-1", "this is an echo msg")
        response := dispatcher.Handle(vEchoMsg)
        fmt.Printf("  echo response: id=%v, cls=%v, content=%v\n", response.ID(), response.Class(), response.Content())
    
        vTimeMsg := delegate.NewTimeMsg("msg-2")
        response = dispatcher.Handle(vTimeMsg)
        fmt.Printf("  time response: id=%v, cls=%v, content=%v\n", response.ID(), response.Class(), response.Content())
    }
    

    测试输出

    $ go test -v delegate_pattern_test.go 
    === RUN   Test_DelegatePattern
    tMsgDispatchDelegate.Handle, handler=*delegate.tEchoMsgHandler, id=msg-1, cls=EchoMsg
      tEchoMsgHandler.Handle, id=msg-1, cls=EchoMsg
      echo response: id=msg-1, cls=EchoMsg, content=this is an echo msg
    tMsgDispatchDelegate.Handle, handler=*delegate.tTimeMsgHandler, id=msg-2, cls=TimeMsg
      tTimeMsgHandler.Handle, id=msg-2, cls=TimeMsg
      time response: id=msg-2, cls=TimeMsg, content=2021-02-05T09:18:45
    --- PASS: Test_DelegatePattern (0.00s)
    PASS
    ok      command-line-arguments  0.002s
    

    IMsg.go

    定义消息接口

    package delegate
    
    type IMsg interface {
        ID() string
        Class() string
        Content() string
    }
    

    BaseMsg.go

    消息的基类, 实现IMsg接口

    package delegate
    
    type BaseMsg struct {
        sID string
        sClass string
        sContent string
    }
    
    func NewBaseMsg(id string, cls string, content string) *BaseMsg {
        return &BaseMsg{
            id, cls, content,
        }
    }
    
    func (me *BaseMsg) ID() string {
        return me.sID
    }
    
    func (me *BaseMsg) Class() string {
        return me.sClass
    }
    
    func (me *BaseMsg) Content() string {
        return me.sContent
    }
    

    EchoMsg.go

    表示原样返回的消息, 用于PING/PONG心跳. 继承自BaseMsg

    package delegate
    
    type EchoMsg struct {
        BaseMsg
    }
    
    func NewEchoMsg(id string, content string) *EchoMsg {
        return &EchoMsg{
            *NewBaseMsg(id, "EchoMsg", content),
        }
    }
    

    TimeMsg.go

    表示获取服务器时间的消息. 继承自BaseMsg

    package delegate
    
    import "time"
    
    type TimeMsg struct {
        BaseMsg
    }
    
    func NewTimeMsg(id string) *TimeMsg {
        return &TimeMsg{
            *NewBaseMsg(id, "TimeMsg", time.Now().Format("2006-01-02T15:04:05")),
        }
    }
    

    IMsgHandler.go

    消息处理器接口. 调度器和具体消息处理器, 均需要实现此接口.

    package delegate
    
    type IMsgHandler interface {
        Handle(request IMsg) IMsg
    }
    

    tMsgDispatchDelegate.go

    全局消息调度器, 是所有客户端消息的统一入口. 用于注册消息处理器, 按类型分发消息. 实现IMsgHandler接口.

    package delegate
    
    import (
        "fmt"
        "reflect"
    )
    
    type tMsgDispatchDelegate struct {
        mSubHandlers map[string]IMsgHandler
    }
    
    func (me *tMsgDispatchDelegate) Register(cls string, handler IMsgHandler) {
        me.mSubHandlers[cls] = handler
    }
    
    func newMsgDispatchDelegate() IMsgHandler {
        it := &tMsgDispatchDelegate{
            mSubHandlers: make(map[string]IMsgHandler, 16),
        }
    
        it.Register("EchoMsg", newEchoMsgHandler())
        it.Register("TimeMsg", newTimeMsgHandler())
    
        return it
    }
    
    
    func (me *tMsgDispatchDelegate) Handle(request IMsg) IMsg {
        if request == nil {
            return nil
        }
    
        handler, ok := me.mSubHandlers[request.Class()]
        if !ok {
            fmt.Printf("tMsgDispatchDelegate.Handle, handler not found: id=%v, cls=%v\n", request.ID(), request.Class())
            return nil
        }
    
        fmt.Printf("tMsgDispatchDelegate.Handle, handler=%v, id=%v, cls=%v\n", reflect.TypeOf(handler).String(), request.ID(), request.Class())
        return handler.Handle(request)
    }
    
    var GlobalMsgDispatcher = newMsgDispatchDelegate()
    

    tEchoMsgHandler.go

    专门处理EchoMsg消息的处理器. 实现IMsgHandler接口.

    package delegate
    
    import "fmt"
    
    type tEchoMsgHandler struct {
    }
    
    func newEchoMsgHandler() IMsgHandler {
        return &tEchoMsgHandler{}
    }
    
    func (me *tEchoMsgHandler) Handle(request IMsg) IMsg {
        fmt.Printf("  tEchoMsgHandler.Handle, id=%v, cls=%v\n", request.ID(), request.Class())
        return request
    }
    

    tTimeMsgHandler.go

    专门处理TimeMsg消息的处理器, 实现IMsgHandler接口.

    package delegate
    
    import (
        "fmt"
        "time"
    )
    
    type tTimeMsgHandler struct {
    }
    
    func newTimeMsgHandler() IMsgHandler {
        return &tTimeMsgHandler{}
    }
    
    func (me *tTimeMsgHandler) Handle(request IMsg) IMsg {
        fmt.Printf("  tTimeMsgHandler.Handle, id=%v, cls=%v\n", request.ID(), request.Class())
    
        timeMsg := request.(*TimeMsg)
        timeMsg.sContent = time.Now().Format("2006-01-02T15:04:05")
        return timeMsg
    }
    

    委派模式小结

    委派模式的优点
    通过任务委派能够将一个大型任务细化,然后通过统一管理这些子任务的完成情况实现任务的跟进,加快任务执行的效率。
    委派模式的缺点
    任务委派方式需要根据任务的复杂程度进行不同的改变,在任务比较复杂的情况下,可能需要进行多重委派,容易造成紊乱。
    _
    (end)

    相关文章

      网友评论

        本文标题:手撸golang 行为型设计模式 委派模式

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