Factory Pattern
Factory pattern: Clients that do not create a logical exposed when you create an object, and through the use of a common interface to point to the newly created object
micro / go-micro in 插件的可插拔
use the factory mode
Application of micro / go-micro factory model
To Registry
the etcd 插件
Case Study
1. Interface
Excerpt: https://github.com/micro/go-micro/blob/master/registry/registry.go
Registry Service Discovery Interface defines as follows:
// The registry provides an interface for service discovery
// and an abstraction over varying implementations
// {consul, etcd, zookeeper, ...}
type Registry interface {
Init(...Option) error
Options() Options
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch(...WatchOption) (Watcher, error)
String() string
}
2. The class implements the interface entity
realization etcd plug: https://github.com/micro/go-plugins/blob/master/registry/etcdv3/etcdv3.go
Excerpt frame as follows:
type etcdv3Registry struct {
// 字段细节略
}
// 省略很多细节代码
func (e *etcdv3Registry) Init(opts ...registry.Option) error {
return configure(e, opts...)
}
func (e *etcdv3Registry) Options() registry.Options {
return e.options
}
func (e *etcdv3Registry) Deregister(s *registry.Service) error {
// 实现细节略
}
func (e *etcdv3Registry) Register(s *registry.Service, opts ...registry.RegisterOption) error {
// 实现细节略
}
func (e *etcdv3Registry) GetService(name string) ([]*registry.Service, error) {
// 实现细节略
}
func (e *etcdv3Registry) ListServices() ([]*registry.Service, error) {
// 实现细节略
}
func (e *etcdv3Registry) Watch(opts ...registry.WatchOption) (registry.Watcher, error) {
return newEtcdv3Watcher(e, e.options.Timeout, opts...)
}
func (e *etcdv3Registry) String() string {
return "etcdv3"
}
func NewRegistry(opts ...registry.Option) registry.Registry {
e := &etcdv3Registry{
options: registry.Options{},
register: make(map[string]uint64),
leases: make(map[string]clientv3.LeaseID),
}
configure(e, opts...)
return e
}
3. Register and create an entity class information
Or Taken: https://github.com/micro/go-plugins/blob/master/registry/etcdv3/etcdv3.go
func init() {
cmd.DefaultRegistries["etcdv3"] = NewRegistry
}
Some of the functions associated with the amount of information:
- import _ “github.com/micro/go-plugins/registry/etcdv3”
- It calls package function init (), to achieve automatic registration entity class and create information
- micro / go-micro via command-line parameters to achieve plug-pluggable
- Through command line parameters, to find ways to create the entity class in cmd.DefaultRegistries
4. Create a plant, to generate the object based on the given entity class information
Excerpt: https://github.com/micro/go-micro/blob/master/config/cmd/cmd.go
Excerpts main code is as follows:
func newCmd(opts ...Option) Cmd {
options := Options{
// 无关代码略
Registries: DefaultRegistries,
// 无关代码略
}
for _, o := range opts {
o(&options)
}
// 无关代码略
cmd := new(cmd)
// 无关代码略
cmd.app.Before = cmd.Before
// 无关代码略
return cmd
}
// 无关代码略
func (c *cmd) Before(ctx *cli.Context) error {
// 无关代码略
// Set the registry
if name := ctx.String("registry"); len(name) > 0 && (*c.opts.Registry).String() != name {
r, ok := c.opts.Registries[name]
if !ok {
return fmt.Errorf("Registry %s not found", name)
}
*c.opts.Registry = r() // 创建在这里,创建实体类对象
// 无关代码略
}
// 无关代码略
}
Just look at the above readers may not understand, a brief description here under:
- When micro / go-micro command-line parameter mechanism used to start a program, change micro-service initialization settings
- micro / go-micro Option explicit mechanism for changing the service initialization micro code provided
Therefore, the command line parameters relevant code will be a bit complicated, the above excerpt also failed to fully show their processes
It is nothing to do with the contents of this article, so you can know the background
other instructions
micro / go-micro simply by 命令行参数
+ 包导入自动注册
+ 工厂类模式
, you can achieve plug-pluggable
the above