工厂方法
lzh2nix opened this issue · comments
Factory Method
在作为新手写代码的时候我们可能都是这么写,在多个地方都写了类似下面这样的代码。
var duck Duck;
if (type == "mallar") {
duck = new MallardDuck();
} else if (type == "decoy") {
duck = new DecoyDuck();
} else {
duck = new RubberDuck();
}
这样就有个问题是当有一个新的需要来来要新增一种duck的时候我们就要修改所有使用这段代码的所有地方,于是乎将这部分代码提到一个公共的函数或者类中。
type Duck interface {
}
func NewDuck(t string) Duck {
var duck Duck
if t == "mallar" {
duck = new(MallardDuck)
} else if t == "decoy" {
duck = new(DecoyDuck)
} else {
duck = new(RubberDuck)
}
return duck
}
其实这就是初代的Factory method。该方式使用不同的input生成不同的对象。在新增一个type的时候只需要在Newxxx中进行变更。
factory method in real world
在emitter中conf文件的解析就使用到了工厂方法。在config.go中定义里以下的 interface
// Provider represents a configurable provider.
type Provider interface {
Name() string
Configure(config map[string]interface{}) error
}
// SecretReader represents a contract for a store capable of resolving secrets.
type SecretReader interface {
Provider
GetSecret(secretName string) (string, bool)
}
// SecretStore represents a contract for a store capable of resolving secrets. On top
// of that, also capable of caching certificates.
type SecretStore interface {
SecretReader
GetCache() (autocert.Cache, bool)
}
然后在不同的provider里都实现了上面的inteface, 这样就可以根据上面配置解析不同的provider, 然后具体对AWS dynamoDB/hashicorp Vault的依赖只限定了在了config包中。
https://github.com/emitter-io/config/blob/master/provider.go
// EnvironmentProvider represents a security provider which uses environment variables to store secrets.
type EnvironmentProvider struct {
lookup func(string) (string, bool)
}
https://github.com/emitter-io/config/blob/master/vault/provider.go
// Provider represents a security provider which uses hashicorp vault to store secrets.
type Provider struct {
client *client // The vault client.
app string // The application ID to use for authentication.
user string // The user ID to use for authentication.
auth bool // Whether the provider is authenticated or not.
}
https://github.com/emitter-io/config/blob/master/dynamo/provider.go
// Provider represents a security provider which uses AWS DynamoDB to store secrets.
type Provider struct {
client *client
}
然后在使用时可以根据需要调用合适的 provider, 这样就把各种provider的Configure
,GetCache
,GetSecret
实现给隐藏起来了。