Это не потому, что структура является вложенной, а потому, что вам нужен получатель-указатель для изменения значения, на которое указывает получатель, в данном случае ваша переменная a
.
Без указателя ваш метод UpdateB
будет обновлять только копию исходного значения структуры.
См. Следующее:
package main
import "fmt"
type B struct {
c int
}
type A struct {
b B
}
func (a *A) UpdateB(n int) {
a.b.c = n
}
func main() {
a := A{b: B{c: 5}}
fmt.Println(a)
a.UpdateB(50)
fmt.Println(a)
}
В опции (A) Вы создаете то, что известно как Функциональный объект или Функтор, это - шаблон разработки, который хорошо документируется.
Два основных преимущества:
Также при использовании платформы внедрения зависимости (Spring, Guice и т.д....), функтор может быть автоматически инициализирован и введен везде, где требуется.
Функциональные объекты экстенсивно используются в библиотеках, например, Стандартной библиотеке шаблонов C++
SampleClass1
SampleClass2
Другая опция, вариант случая A, следующая:
class SampleClass3 { SampleClass3( IWorker workerA, IWorker workerB ); WorkResult doWork(); }
Преимущества:
Более трудно сделать объект дефектным, так как Вы обязаны предоставлять всех рабочих, которые необходимы во время создания (в отличие от случая A).
Можно все еще нести состояние в SampleClass3 и/или одном из рабочих. (Это невозможно в случае, если B.)
Недостатки:
Другая опция:
Класс IWorker:
статический WorkResult doWork (Iworker a, Iworker b);
A) плохой дизайн, потому что он позволяет объекту быть дефектным (один, или оба из классов рабочего, возможно, не были установлены).
B) может быть хорошим. Сделайте это статичным хотя, если Вы не зависите от внутреннего состояния SampleClass2
IMO 2-й подход выглядит лучше, он требует, чтобы вызывающая сторона использовала меньше кода для выполнения задачи. 2-й подход менее подвержен ошибкам, вызывающая сторона не должны волноваться, что объект не мог бы быть инициализирован полностью.
Если больше чем один метод зависит от IWorker a и IWorker b, я говорю, действительно выбирают A.
Если только doWork () использует и IWorker a и IWorker b, то выберите B.
Кроме того, какова реальная цель Вашего SampleClass? doWork немного походит на служебный метод mroe, чем что-либо еще.
Как насчет того, чтобы вместо этого определить a WorkDelegate
(или альтернативно интерфейс, имеющий сингл doWork
метод без аргумента), который просто возвращает a WorkResult
и позволяющие отдельные классы решают, как они реализуют его? Таким образом, Вы не ограничиваетесь преждевременными решениями.