选项模式(option)

选项模式(option)

  • Option模式的专业术语为:Functional Options Pattern(函数式选项模式)
  • Option模式为golang的开发者提供了将一个函数的参数设置为可选的功能,也就是说我们可以选择参数中的某几个,并且可以按任意顺序传入参数。
  • 应用场景:
  • 1.一个函数需要不同的参数;而众所周知,Golang语言目前不支持函数重载,所以就可以使用这种可变长参数的形式来模拟函数重载这种情况。
  • 2.一个复杂的结构体,在业务中可能会频繁的添加字段,如果把NewXXX( ) XXX 方法写死,那么后续修改起来非常麻烦。此时使用选项模式,对其初始化,新增一个字段,就新增对应的一个函数来处理字段的初始化,应用程序的扩展性大大的提高了。
  • 3.可读性好,给代码的维护带来了便利。

代码

package main
import (
	"fmt"
)

//使用场景,大量修改一个结构体,增加字段值,初始化极其麻烦
//引入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()
}



//另一个例子
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)
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值