当前位置: 首页 > 工具软件 > Hero-Go > 使用案例 >

选项模式-Golang设计模式

谷梁楚青
2023-12-01

选项模式-Golang设计模式

tips:对结构体中的字段,会频繁变化、需要灵活配置、有默认值的场景,可能会用到 Option 模式。

1.场景

往简单来说,有下面这一个需求:

如果创造了一个英雄,我想修改它的属性,怎么才能方便的去修改,包括之后新增的字段,如果不直接用结构体.字段的形式,保证了修改英雄属性的安全性,

2021/12/30 09:30:52 英雄创造后属性为: &{1001 Default 1 1 map[]}
2021/12/30 09:30:52 英雄魔改后属性为: &{1001 libai 3 10 map[name:libai]}

Option 模式

Option 模式的专业术语为:Functional Options Pattern(函数式选项模式)函数的参数传递是一个 Options。

为开发者提供了将一个函数的参数设置为可选的功能,每次新增选项时,可以不改变接口保持兼容,并且参数无顺序要求。

2. option模式实现 Hero

package main

import "log"

type Hero struct {
	HeroId  int
	Name    string // 名字
	SkillId int    // 技能Id
	Speed   int    // 移动速度
	Extra   map[string]string
}

type Option struct {
	Change func(hero *Hero)
}

func NewHeroTemplate() *Hero {
	return &Hero{
		HeroId:  1001,
		Name:    "Default",
		SkillId: 1,
		Speed:   1,
		Extra:   make(map[string]string),
	}
}

// 改变英雄名字
func WithName(name string) *Option {
	return &Option{Change: func(hero *Hero) {
		hero.Name = name
	}}
}

// 改变技能Id
func WithSkillId(skillId int) *Option {
	return &Option{Change: func(hero *Hero) {
		hero.SkillId = skillId
	}}
}

// 改变速度
func WithSpeed(speed int) *Option {
	return &Option{Change: func(hero *Hero) {
		hero.Speed = speed
	}}
}

// 增加扩展信息
func WithExtra(key string, value string) *Option {
	return &Option{Change: func(hero *Hero) {
		hero.Extra[key] = value
	}}
}

func GetHero(options ...*Option) *Hero {
	hero := NewHeroTemplate()
	for _, opt := range options {
		opt.Change(hero)
	}
	return hero
}

func main() {
	hero:=GetHero(
		WithName("libai"),
		WithSkillId(2),
		WithSkillId(3),
		WithSpeed(2),
		WithSpeed(10),
		WithExtra("name", "libai"))
	log.Println("英雄创造后属性为:",hero)
}

此时如果我们要新加一个字段,只需要对应增加一个WithXXX的方法,在原来的调用代码处以新增代码的方式调用,以很小的成本去新增一个扩展同理,这个编写代码的方式也可以作用在配置类上,新增配置,或者Server服务器新增参数,新增服务等等

缺点:就是字段多的话,对应的方法也多,但注意了使用场景避免缺点去使用才是一名优秀的攻城狮!

 类似资料: