Go 设计模式之选项模式 / 优雅添加传参默认值

创建一个文件options.go

// 意图:通过修改选项,创建出功能不同的实例
// 解决:由于go语言没有默认值,继承,多态,所有使用选项模式来达到默认值,多态的效果

package options

import "fmt"

// 士兵
type Soldier struct {
	arms        string // 兵种
	attack      int    // 攻击力
	defense     int    // 防御力
	damageRange int    // 伤害范围
}

func (s *Soldier) String() string {
	return fmt.Sprintf("成功创建一位%s,攻击:%d,防御:%d,伤害范围:%d", s.arms, s.attack, s.defense, s.damageRange)
}

const (
	defaultAttack      = 10
	defaultDefense     = 10
	defaultDamageRange = 1
)

type options struct {
	attack      int
	defense     int
	damageRange int
}

type Option interface {
	apply(*options)
}

type optionFunc func(*options)

func (f optionFunc) apply(o *options) {
	f(o)
}

func WithAttack(attack int) Option {
	return optionFunc(func(o *options) {
		o.attack = attack
	})
}

func WithDefense(defense int) Option {
	return optionFunc(func(o *options) {
		o.defense = defense
	})
}

func WithDamageRange(damageRange int) Option {
	return optionFunc(func(o *options) {
		o.damageRange = damageRange
	})
}

// 创建一个士兵
func NewSoldier(arms string, opts ...Option) (*Soldier, error) {
	// 设置默认选项
	options := options{
		attack:      defaultAttack,
		defense:     defaultDefense,
		damageRange: defaultDamageRange,
	}

	// 使用自定义选项覆盖默认选项
	for _, o := range opts {
		o.apply(&options)
	}

	return &Soldier{
		arms:        arms,
		attack:      options.attack,
		defense:     options.defense,
		damageRange: options.damageRange,
	}, nil
}

单元测试options_test.go

package options

import (
	"fmt"
	"testing"
)

func TestNewSoldier(t *testing.T) {
	options := []Option{
		WithAttack(10),
		WithDefense(5),
		WithDamageRange(5),
	}
	c, err := NewSoldier("弓箭手", options...)
	if err != nil {
		fmt.Println("err", err)
	}
	fmt.Println(c)
}

执行go test

成功创建一位弓箭手,攻击:10,防御:5,伤害范围:5
PASS
ok      opeions 0.006s
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值