Opts Pattern
迪丽瓦拉
2024-03-30 01:22:14
0

Opts Pattern

通常情况下,创建一个新的对象会使用默认构造器。

假设现在我们要准备一个家庭医药包,里面有抵抗新冠的一些常用药,比如莲花清瘟,999感冒灵颗粒,藿香正气片 etc.

package mainimport "fmt"// MedicalKit contains medicine that helps alleviate symptoms of COVID-19 virus
type MedicalKit struct {// 莲花清瘟LianHuaQingWenCapsule int// 999GanMaoLingKeLi int// 藿香正气片LophanthusAntiFebrileTablet int
}// NewMedicalKit create a new default medical kit
func NewMedicalKit() *MedicalKit{return &MedicalKit{LianHuaQingWenCapsule: 1,GanMaoLingKeLi: 1,LophanthusAntiFebrileTablet: 1,}
}func main() {kit:=NewMedicalKit()fmt.Println(kit)
}

那现在如果要创建的同时,修改对象的状态,怎么办?

你会很容易想到带参构造器:

// NewMedicalKit create a new default medical kit
func NewMedicalKit(LianHuaQingWenCapsule int,LophanthusAntiFebrileTablet int,GanMaoLingKeLi int,) *MedicalKit{return &MedicalKit{LianHuaQingWenCapsule: LianHuaQingWenCapsule,GanMaoLingKeLi: GanMaoLingKeLi,LophanthusAntiFebrileTablet: LophanthusAntiFebrileTablet,}
}

但是这样有一个问题,如果我只想传入其中一个参数,保持其他为默认值,在调用的时候,我不得不将参数全部传入。

kit:=NewMedicalKit(1,2,3)

另外一个问题是我需要记住参数传入的顺序,否则就会有差错。

那有没有一种方法,让我可以实现不需要关心参数传入顺序且不用传入非必要参数呢?答案是Opts模式

Opts模式

Opts模式相比默认构造器有如下优势

  • 封装内部对象如何更改状态自身
  • 只需要向构造器传入想修改的参数,默认的不需要传
  • 不需要去关心向构造器传入的参数的顺序
package mainimport "fmt"// MedicalKit contains medicine that helps alleviate symptoms of COVID-19 virus
type MedicalKit struct {// 莲花清瘟LianHuaQingWenCapsule int// 999GanMaoLingKeLi int// 藿香正气片LophanthusAntiFebrileTablet int
}var (DefaultLianHuaQingWenCapsuleCount =1DefaultGanMaoLingKeLiCount=1DefaultLophanthusAntiFebrileTabletCount=1
)
// MedicalKitOptions 可以更改构造器行为
type MedicalKitOptions func(*MedicalKit)func NewMedicalKit(opts  ...MedicalKitOptions) *MedicalKit{kit:=&MedicalKit{LophanthusAntiFebrileTablet: DefaultLophanthusAntiFebrileTabletCount,GanMaoLingKeLi: DefaultGanMaoLingKeLiCount,LianHuaQingWenCapsule: DefaultLianHuaQingWenCapsuleCount,}// 执行每个option函数for _, opt :=range opts{opt(kit)}return kit
}func main() {with999:= func(count int) MedicalKitOptions{return func(k *MedicalKit){k.GanMaoLingKeLi=count}}withLianHua:= func(count int) MedicalKitOptions{return func(k *MedicalKit) {k.LianHuaQingWenCapsule=count}}// without need to pass all argumentskit:=NewMedicalKit(with999(2),withLianHua(3))fmt.Println(kit)}

相关内容