Option mode (option)

Option mode (option)

  • The professional term for Option mode is: Functional Options Pattern (Functional Options Pattern)
  • Option mode provides golang developers with the ability to set the parameters of a function as optional. That is to say, we can select some of the parameters and pass in the parameters in any order.
  • For example, for special scenarios that require different parameters, C++ can directly use overloading to write any function with the same name, and use the same function name when calling any scenario; but in the same case, in golang we must Different scenarios use different functions, and the parameter passing method may be different when written by different people, which will lead to poor code readability and poor maintainability.

Advantages and disadvantages of Option mode

advantage
  1. Support for passing multiple parameters, and maintain compatibility when the number and type of parameters change
  2. Pass parameters in any order
  3. Support default value
  4. Easy to expand
Disadvantage
  1. Add many functions and increase the cost
  2. When the parameters are not too complicated, try to use them sparingly

Code

package main
//options_ok
import (
	"fmt"
)


/**
Option模式的优缺点
优点
支持传递多个参数,并且在参数个数、类型发生变化时保持兼容性
任意顺序传递参数
支持默认值
方便拓展
缺点
增加许多function,成本增大
参数不太复杂时,尽量少用

1. 需要Option选项得对象,里面是每一个配置
2. 需要一个Option得接口,拥有一个设置option得函数
3. 需要一个自定义类型得func,实现了Option接口
4. func要返回一个Option类型得接口,并且参数为要设置得内容
*/


//使用场景,大量修改一个结构体,增加字段值,初始化极其麻烦
//引入option模式后,直接加一个属性和一个函数就可以搞定
type Message struct {
    
    
	id      int
	name    string
	address string
	phone   int
}

func (msg Message) String() {
    
    
	fmt.Printf("ID:%d \n- Name:%s \n- Address:%s \n- phone:%d\n", msg.id, msg.name, msg.address, msg.phone)
}

func New(id, phone int, name, addr string) Message {
    
    
	return Message{
    
    
		id:      id,
		name:    name,
		address: addr,
		phone:   phone,
	}
}

type Option func(msg *Message)

var DEFAULT_MESSAGE = Message{
    
    id: -1, name: "-1", address: "-1", phone: -1}

func WithID(id int) Option {
    
    
	return func(m *Message) {
    
    
		m.id = id
	}
}

func WithName(name string) Option {
    
    
	return func(m *Message) {
    
    
		m.name = name
	}
}

func WithAddress(addr string) Option {
    
    
	return func(m *Message) {
    
    
		m.address = addr
	}
}

func WithPhone(phone int) Option {
    
    
	return func(m *Message) {
    
    
		m.phone = phone
	}
}


func NewByOption(opts ...Option) Message {
    
    
	msg := DEFAULT_MESSAGE
	for _, o := range opts {
    
    
		o(&msg)
	}
	return msg
}

func NewByOptionWithoutID(id int, opts ...Option) Message {
    
    
	msg := DEFAULT_MESSAGE
	msg.id = id
	for _, o := range opts {
    
    
		o(&msg)
	}
	return msg
}

func main() {
    
    
	message1 := New(1, 123, "message1", "cache1")
	message1.String()

	message2 := NewByOption(
		WithID(2),
		WithName("message2"),
		WithAddress("cache2"),
		WithPhone(456),
	)
	message2.String()

	message3 := NewByOptionWithoutID(
		3,
		WithAddress("cache3"),
		WithPhone(789),
		WithName("message3"),
	)

	message3.String()

	main1()
}

/*
Output
ID:1
- Name:message1
- Address:cache1
- phone:123
ID:2
- Name:message2
- Address:cache2
- phone:456
ID:3
- Name:message3
- Address:cache3
- phone:789
*/





//例2

type OptionFunc func(op *OptionMenu)

type OptionMenu struct {
    
    
	op1 string
	op2 string
	op3 int
	op4 int
	//......可能还会有跟多的属性加入,这给实例化带来了巨大的问题
}

func InitOptions(optionFuncs ...OptionFunc) OptionMenu {
    
    
	option := OptionMenu{
    
    }
	for _, op := range optionFuncs {
    
    
		op(&option)
	}
	return option
}

func WithOp1(op1 string) OptionFunc {
    
    
	return func(op *OptionMenu) {
    
    
		op.op1 = op1
	}
}

func WithOp2(op2 string) OptionFunc {
    
    
	return func(op *OptionMenu) {
    
    
		op.op2 = op2
	}
}

func WithOp3(op3 int) OptionFunc {
    
    
	return func(op *OptionMenu) {
    
    
		op.op3 = op3
	}
}

func WithOp4(op4 int) OptionFunc {
    
    
	return func(op *OptionMenu) {
    
    
		op.op4 = op4
	}
}

func main1() {
    
    
	op := InitOptions(
		WithOp1("op1"),
		WithOp2("op2"),
		WithOp3(3),
		WithOp4(4),
	)
	fmt.Printf("%#v\n", op)
}

Guess you like

Origin blog.csdn.net/dawnto/article/details/112974179