Как стать автором
Обновить

Комментарии 7

Паттерн крутой, но так он меняет cостояние объекта, применяя его в методах структуры стреляете себе в ногу, например необходимо сбрасывать значения полей при повторных вызовах.

Есть 2 мнения на этот счет. Однако мой подход приведен для наглядности примера с паттерном.

Можно сделать функцию, которая будет сбрасывать значение или возвращать null по умолчанию.
Не вижу почему это выстрел себе в ногу. Если возможно, буду благодрен за пример

В том и проблема что можно написать любую функцию, которая будет менять состояние ScannedItem, и будет очень сложно контролировать все возможные варианты, например так:

func (item *ScannedItem) ChangeGS1(value bool) ScanFunc {
	return func(item *ScannedItem) {
		item.GS1 = value
	}
}

и тогда в зависимости от порядка опций в вызове ScannedItem айтем с одними и теме же Datamatrix может быть и валидным и не валидным

Option pattern удобно и более правильно использовать для установки параметров структуры отличных от дефолтных по умолчанию, например так:

func NewScannedItem(opts ...ScanFunc) *ScannedItem {
	item := &ScannedItem{}
	for _, fn := range opts {
		fn(item)
	}

	return item
}

func WithGS1(value bool) ScanFunc {
	return func(item *ScannedItem) {
		item.GS1 = value
	}
}

func main() {
	NewScannedItem(WithGS1(true))
}

В вашем случае, если в методе Scan надо научиться запускать кастомные валидаторы, то можно в структуру добавить validators []ScanFunc, задавать их список в конструкторе с так же с помощью opts, а в методе Scan вызывать

Спасибо за пример - асбсолютно согласен!

type OptFunc func(*Opts)

type Opts struct {
	maxConn int
	tls     bool
}

func WithTLS() OptFunc {
	return func(o *Opts) {

		o.tls = true

	}

}

func MaxConn(con_number int) OptFunc {
	return func(o *Opts) {

		o.maxConn = con_number

	}

}

func DefaultCon() Opts {
	return Opts{
		10, false,
	}

}

type Server struct {
	Opts
}

func NewServer(opts ...OptFunc) *Server {

	o := DefaultCon()

	for _, fn := range opts {

		fn(&o)

	}

	return &Server{o}

}

Можно будет даже дополнить статью им.

Согласен с @lelikPtz. Опции лучше использовать только в конструкторах!

Для смены состояний предлагаю использовать явные сеттеры.

Выглядит как сложное решение непонятно какой даже проблемы. Чем это лучше последовательного вызова Check-функций? Их все равно надо написать и передать в Scan

	a.Scan()
	a.CheckValidWithReason()
	// a.CropDatamatrixOption()
	a.CheckGS1Option()

Я ещё понимаю если бы было

	a, err := ScanWithOptions(CheckValidWithReason(), CheckGS1Option())

обычно так это и используют

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории