Golang中如何优雅实现模版方法

模版方法是大厂复杂业务逻辑中使用的最多的一种设计模式了,在一些业务庞大、成熟的代码中真的可以说是随处可见。常见的业务场景比方说执行器、校验器之类;其主要目的是可维护性。新增一个执行器/校验器之需要写差异化逻辑,不会把代码搞成烟囱那种难以看懂的模式。

对于Java来说,模版方法的实现方式非常简单,一般只需要一个抽象类,和一堆实现类就可以实现。

具体操作是,先创建抽象类,定义模板方法规定操作顺序,再设抽象方法作步骤占位,由子类继承并重写抽象方法,调用模板方法时按顺序执行,依子类重写内容展现差异化行为。

但是在golang中没有继承、没有抽象类,网上不少人强行用java的方式些golang,到最后反而让代码变地非常难以理解。

经过摸索之后,我写了一套golang当中实现模版方法模式的代码,主要使用了golang组合为先、面向接口编程的编程思想。其中使用了一个接口,一个模版类和接口的实现类,其中实现不当的地方,欢迎大家讨论

package templatemethod

import "fmt"

// 实现方需要实现的差异化接口
type DownloadLogic interface {
  download(uri string)
  save()
}

type HTTPDownloader struct{}
func (d *HTTPDownloader) download(uri string) {}
func (d *HTTPDownloader) save()               {}

type FTPDownloader struct{}
func (d *FTPDownloader) download(uri string) {}
func (d *FTPDownloader) save()               {}

type DownLoadExecutor struct {
  // 组合一个接口
  downloader DownloadLogic
}
func (d *DownLoadExecutor) doSomeOtherThings(){}

// 模版方法,进行逻辑编排
func (d *DownLoadExecutor) doDownloadExecute(uri string) {
  doSomeOtherThings()
  d.downloader.download(uri)
  doSomeOtherThings()
  d.downloader.save()
  doSomeOtherThings()
}

// DownloadExecutorsMap 提供根据executor名称拿到下载器的能力
// 某些时候「比如校验器」更多是维护成一个list
var DownloadExecutorsMap = map[string]*DownLoadExecutor{
  "http": {downloader: &HTTPDownloader{}},
  "ftp":  {downloader: &FTPDownloader{}},
}

// Use 模拟使用方的业务逻辑
func Use() error {
  executor, ok := DownloadExecutorsMap["http"]
  if !ok {
	return fmt.Errorf("http download executor not found")
  }
  executor.doDownloadExecute("https://www.google.com")
  return nil
}

全部评论
佬,太强了啊,教教我golang
1 回复 分享
发布于 01-11 21:00 陕西
不错呀
点赞 回复 分享
发布于 01-11 23:37 四川

相关推荐

评论
1
6
分享

创作者周榜

更多
牛客网
牛客企业服务