💬
Functional Option Patterns
Functional Option パターン
はじめまして!エンジニアのビクトルと申します。
この技術がどのようにしてオブジェクトファクトリーの作成について説明しましょー。
オブジェクトをN個のパラメータを使用して作成するのに苦労していますか?もし1つ以上のパラメータを追加する場合や必要がない場合はどうなるのでしょうか?ここで、Functional Optionパターンのパワーです!
コード書きましょ
例えば、あるコードで。。。
type person struct {
name, surName, middleName string
}
func NewPerson(name, surName, middleName string) *person {
return &person{
name: name,
surName: surName,
middleName: middleName,
}
}
国によって、人々はミドルネームを持っている可能性があります。その場合、NewPerson()
関数を使用する際に、middleName
パラメータには空文字を入り、少し読みにくいになっています。オブジェクトの作成に必要なパラメータのみを使用する方法はどのように実現できるでしょうか?また、構造体に新しいプロパティを追加したい場合はどうなるのでしょうか?
パターン使いましょ!
2つの方法で書くことができます:
- Applied functions
- Normal functions
Applied functions
type person struct {
name, surName, middleName string
}
type Option interface {
apply(*person)
}
type (
nameOption string
surNameOption string
middleNameOption string
)
func (n nameOption) apply(p *person) {
p.name = string(n)
}
func (n surNameOption) apply(p *person) {
p.surName = string(n)
}
func (n middleNameOption) apply(p *person) {
p.middleName = string(n)
}
func WithName(name string) PersonOption {
return nameOption(name)
}
func WithSurName(surName string) PersonOption {
return surNameOption(surName)
}
func WithMiddleName(name string) PersonOption {
return middleNameOption(name)
}
func defaultPerson() *person {
return &person{
name: "anonymous",
}
}
func NewPerson(pOpts ...PersonOption) Person {
defOpts := defaultPerson()
for _, opt := range pOpts {
opt.apply(defOpts)
}
return defOpts
}
Normal functions
type (
person struct {
name string
surName string
middleName string
}
Option func(*person)
)
func WithName(name string) Option {
return func(parameter *person) {
parameter.name = name
}
}
func WithSurName(surName string) Option {
return func(parameter *person) {
parameter.surName = surName
}
}
func WithMiddleName(surName string) Option {
return func(parameter *person) {
parameter.surName = surName
}
}
func defaultPerson() *person {
return &person{
name: "anonymous",
}
}
func NewPerson(opts ...Option) *person {
fn := defaultPerson()
for _, opt := range opts {
opt(fn)
}
return fn
}
使い方
func main() {
person1 := NewPerson(
WithName("victor"),
WithSurName("massuru"),
WithMiddleName("kinniku"),
)
}
そして、必要なパラメータを追加して使用することができます。
でも。。。こいう書き方長くて。。。自動化できないのでしょうか?
。。。あります!
Happy Hacking!
Related doc:
Discussion