Go语言实现Template Pattern

栏目: Go · 发布时间: 5年前

内容简介:通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。、

Template Pattern设计模式 中的经典模式,它定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。其UML示意图如下,

Go语言实现Template Pattern

通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。、

最近在用 go 语言开发中,发现有很多地方可以用上述模式来开发,这样可以使得代码更简洁,易于阅读,降低维护成成本。但是,go语言对面向对象编程支持不像java,scala,C++那样彻底。go原生的interface无法实现abstract方法,所以无法直接实现上述模式。因此,需要一些特殊的技巧来实现子类的方法调用。

首先,定义模板类,以及模板方法,

// 定义模板类,使用struct,而不是interface
type DBLoader struct {
   Sql    func() string
   Assign func(row *[]map[string]string) error
}

// 实现模版方法
func (l *DBLoader)Load(db_conf *mysql.DbConfig) error {
   sql := l.Sql() // 拼接sql	
   // MySQL查询
   err = l.Assign(&rst)   // 解码数据
   // ... 仅用于演示,其他逻辑这里忽略
   return nil
}

派生子类,实现特定逻辑,

// go继承
type MyLoader struct {
   DBLoader
   my_value string
}

// 实现 sql 逻辑
func (m *MyLoader) Sql() string {
   return "select * ..."
}


// 实现赋值逻辑
func (m *MyLoader) Assign(row *[]map[string]string) error {
   m.my_value = "bourneli"
   return nil
}

// 将子类特定函数赋值给父类,以便在模板函数中调用
func NewMyLoader() *MyLoader {
   m := MyLoader{}
   m.DBLoader.Sql = m.Sql // 非常重要
   m.DBLoader.Assign = m.Assign // 非常重要
   return &m
}

最后,Mock MySQL查询操作,测试子类逻辑是否正确执行,

func TestDBLoader_Load(t *testing.T) {
   monkey.Patch(mysql.Query, func(d *mysql.DbConfig, query string, args ...interface{}) ([]map[string]string, error) {
      return []map[string]string{}, nil
   }
   defer monkey.UnpatchAll()

   Convey("",t, func(){
      m := NewMyLoader()
      So(m.my_value, ShouldEqual, "")
      err := m.Load(nil)
      So(err, ShouldBeNil)
      So(m.my_value, ShouldEqual, "bourneli")
   })
}

func TestDBLoader_QueryError(t *testing.T) {
   monkey.Patch(mysql.Query, func(d *mysql.DbConfig, query string, args ...interface{}) ([]map[string]string, error) {
      return []map[string]string{}, fmt.Errorf("some error")
   })
   defer monkey.UnpatchAll()

   Convey("",t, func(){
      m := NewMyLoader()
      So(m.my_value, ShouldEqual, "")
      err := m.Load(nil)
      So(err, ShouldNotBeNil)
   })
}

希望上面的技巧对读者有所帮助。笔者的主要参考资料为 Elegant way to implement template method pattern in Golang


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构与算法分析

数据结构与算法分析

韦斯 / 机械工业 / 2007-1 / 55.00元

本书是国外数据结构与算法分析方面的标准教材,使用最卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计)。   随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也在增长。本书把算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面、缜密严格,并细致讲解精心构造程序的方法。   第......一起来看看 《数据结构与算法分析》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试