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


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

查看所有标签

猜你喜欢:

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

Operating System Algorithms

Operating System Algorithms

Nathan Adams、Elisha Chirchir / CreateSpace Independent Publishing Platform / 2017-4-21 / USD 39.15

Operating System Algorithms will walk you through in depth examples of algorithms that you would find in an operating system. Selected algorithms include process and disk scheduling.一起来看看 《Operating System Algorithms》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

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

HTML 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具