golang设计模式---模板模式 - Go语言中文社区

golang设计模式---模板模式


场景

当要做一件事儿的时候,这件事儿的流程和步骤是固定好的,但是每一个步骤的具体实现方式是不一定的。这个时候就可以使用模板模式。

业务流程

在这里插入图片描述

接口

type BankBusinessHandler interface {
 // 排队拿号
 TakeRowNumber()
 // 等位
 WaitInHead()
 // 处理具体业务
 HandleBusiness()
 // 对服务作出评价
 Commentate()
 // 钩子方法,
    // 用于在流程里判断是不是VIP, 实现类似VIP不用等的需求
 checkVipIdentity() bool
}

模板方法

type BankBusinessExecutor struct {
 handler BankBusinessHandler
}
// 模板方法,处理银行业务
func (b *BankBusinessExecutor) ExecuteBankBusiness () {
 // 适用于与客户端单次交互的流程
 // 如果需要与客户端多次交互才能完成整个流程,
    // 每次交互的操作去调对应模板里定义的方法就好,并不需要一个调用所有方法的模板方法
 b.handler.TakeRowNumber()
 if !b.handler.CheckVipIdentity() {
  b.handler.WaitInHead()
 }
 b.handler.HandleBusiness()
 b.handler.Commentate()
}

DefaultBusinessHandler

能达到减少重复实现相同逻辑的效果。
并没有实现我们想要留给具体子类实现的HandleBusiness方法,这样 DefaultBusinessHandler 就不能算是BankBusinessHandler接口的实现,这么做是为了这个类型只能用于被实现类包装,让 Go 语言的类型检查能够帮我们强制要求,必须用存款或者取款这样子类去实现HandleBusiness方法,整个银行办理业务的流程的程序才能运行起来。

type DefaultBusinessHandler struct {
}
func (*DefaultBusinessHandler) TakeRowNumber() {
 fmt.Println("请拿好您的取件码:" + strconv.Itoa(rand.Intn(100)) +
  " ,注意排队情况,过号后顺延三个安排")
}

func (dbh *DefaultBusinessHandler) WaitInHead() {
 fmt.Println("排队等号中...")
 time.Sleep(5 * time.Second)
 fmt.Println("请去窗口xxx...")
}

func (*DefaultBusinessHandler) Commentate() {

 fmt.Println("请对我的服务作出评价,满意请按0,满意请按0,(~ ̄▽ ̄)~")
}

func (*DefaultBusinessHandler) CheckVipIdentity() bool {
 // 留给具体实现类实现
 return false
}

func NewBankBusinessExecutor(businessHandler BankBusinessHandler) *BankBusinessExecutor {
 return &BankBusinessExecutor {handler: businessHandler}
}

业务实现

type DepositBusinessHandler struct {
 *DefaultBusinessHandler
 userVip bool
}

// 通用的方法还可以抽象到BaseBusinessHandler里,组合到具体实现类里,减少重复代码(实现类似子类继承抽象类的效果)
func (*DepositBusinessHandler) TakeRowNumber() {
 fmt.Println("请拿好您的取件码:" + strconv.Itoa(rand.Intn(100)) +
  " ,注意排队情况,过号后顺延三个安排")
}

func (dh *DepositBusinessHandler) WaitInHead() {
 fmt.Println("排队等号中...")
 time.Sleep(5 * time.Second)
 fmt.Println("请去窗口xxx...")
}

func (*DepositBusinessHandler) HandleBusiness() {
 fmt.Println("账户存储很多万人民币...")
}

func (dh *DepositBusinessHandler) CheckVipIdentity() bool {
 return dh.userVip
}


func (*DepositBusinessHandler) Commentate() {

 fmt.Println("请对我的服务作出评价,满意请按0,满意请按0,(~ ̄▽ ̄)~")
}
func NewBankBusinessExecutor(businessHandler BankBusinessHandler) *BankBusinessExecutor {
 return &BankBusinessExecutor {handler: businessHandler}
}

func main()  {
 dh := &DepositBusinessHandler{userVip: false}
 bbe := NewBankBusinessExecutor(dh)
 bbe.ExecuteBankBusiness()
}

缺点

  1. 由于继承关系自身的缺点,如果父类添加新的抽象方法,则所有子类都要改一遍。
    解决:把某个核心流程提炼成固定步骤的时候再应用

参考资料

卡尔文_ 网管叨bi叨

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/newbieJ/article/details/128447439
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2022-12-29 19:11:58
  • 阅读 ( 163 )
  • 分类:设计模式

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢