七叶笔记 » golang编程 » golang变相实现抽象类

golang变相实现抽象类

golang里的 struct 只能有属性, interface只能有方法定义。这点在 java 里很好实现的 abstract class 在这里就不能直接实现, 可以通过struct和interface的结合定义,实现抽象类的类似的功能。

直接上代码:

代码都来之与项目

GitHub – golang fot xxl-job executor

在这个项目里,重构了executor和默认的RestfulExecutor的实现方式, 就是采用了上述的方式。

先定义接口

 // executor 执行器
type executor interface {
   //  Init 
   // 初始化执行器
   Init(opts ...Option)
   // Run 启动服务
   Run() error
   // Registry 注册执行器到 调度中心 
   Registry()
   // UnRegistry 从调度中心在注销执行器
   UnRegistry() error
   // SetLogHandler 日志handler
   SetLogHandler(handler LogHandler)
   // Stop 停止服务
   Stop()
   //  Request Callback 执行后回调请求给调度中心
   RequestCallback(task *Task, code int64, msg string)
   // RegTask
   // 注册任务
   RegTask(pattern string, task TaskFunc)
}  

然后定义我们需要的 抽象类

 type Executor struct {
   executor
   //  private 
   opts    Options
   address string
   regList *taskPool //注册任务列表
   runList *taskPool //正在执行任务列表
   log     log4go.Logger

   logHandler LogHandler //日志查询handler

   // inner
   _impl executor  // 这里很关键,是实现抽象类的重要地方
}

// 这里很关键,是实现抽象类的重要地方,封装一个wrap方法,
func (e * Executor ) wrap(_wrap executor) {
e._impl = _wrap
}  

实现抽象类里的主要方法

 func (e *Executor) Init(opts ...Option) {
   for _, o := range opts {
      o(&e.opts)
   }

   e.log = e.opts.logger

   e.regList = &taskPool{
      data: make(map[string]*Task),
   }
   e.runList = &taskPool{
      data: make(map[string]*Task),
   }

   e.address = e.opts.ExecutorIp + ":" + e.opts.ExecutorPort

   e.log.Info("%v %v", EXECUTOR4G_VERSION, e.address)

   go e.Registry()  // 这里的Regstry是子类需要实现的方法
}


//  Registry  注册执行器到调度中心
func (e *Executor) Registry() {  /// 用wrap方式把调用交换具体的子类
e._impl.Registry()
}  

子类实现

 type RestFulExecutor struct {
   Executor
   mu sync.RWMutex
}

// Registry
// 注册执行器到调度中心
func (e *RestFulExecutor) Registry() {

t := time.NewTimer(time.Second * 0) //初始立即执行
defer t.Stop()
....
}  

最关键的地方,调用

 func newExecutor(opts ...Option) executor {
   //var exec executor

   options := newOptions(opts...)

   if options.executorImpl == nil {
      // 变相的抽象类的实现
      e := &RestFulExecutor{}
      e.wrap(e)  // 最关键的地方,使用wrap把具体实现子类包装进返回接口

      e.opts = options
      return e
   } else {
      return options.executorImpl
   }
}  

具体代码可以查看项目中的源码

项目地址

推荐几个好工具

相关文章