lzh2nix / articles

用 issue 来管理个人博客

Home Page:https://github.com/lzh2nix/articles

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

工厂方法

lzh2nix opened this issue · comments

commented

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的ConfigureGetCacheGetSecret 实现给隐藏起来了。