Answer
t.me/js_testОтвет:
class PersonBuilder {
constructor(person) {
if (person instanceof Person) {
this.person = person;
} else {
this.person = new Person();
}
}
get lives() {
return new PersonAddressBuilder(this.person);
}
get works() {
return new PersonJobBuilder(this.person);
}
build() {
return this.person;
}
}
class PersonJobBuilder extends PersonBuilder {
constructor(person) {
super(person);
}
at(companyName) {
this.person.companyName = companyName;
return this;
}
asA(position) {
this.person.position = position;
return this;
}
earning(annualIncome) {
this.person.annualIncome = annualIncome;
return this;
}
}
class PersonAddressBuilder extends PersonBuilder {
constructor(person) {
super(person);
}
at(streetAddress) {
this.person.streetAddress = streetAddress;
return this;
}
withPostcode(postcode) {
this.person.postcode = postcode;
return this;
}
inCity(city) {
this.person.city = city;
return this;
}
}
Объяснение:
Конструктор класса PersonBuilder принимает инстанс класса Person и сохраняет его во внутреннее поле, если же person не был передан то нужно создать свой и тоже сохранить. Геттер lives возвращает инстанс вспомогательного класса PersonAddressBuilder, он наследуется от нашего основного билдера и имеет методы at, withPostcode и inCity которые мутируют поля внутреннего person. Геттер works возвращает инстанс вспомогательного класса PersonJobBuilder, он тоже наследуется от нашего основного билдера и имеет методы at, asA и earning которые тоже мутируют поля внутреннего person. Как видите, реализовав паттерн builder, у нас получилось разделить создание Person на несколько этапов.
Код для проверки:
class Person {
streetAddress = null;
postcode = null;
city = null;
companyName = null;
position = null;
annualIncome = null;
summary() {
return `Address: ${this.streetAddress}, ${this.postcode}, ${this.city}
Employed at ${this.companyName} as a ${this.postcode} earning ${this.annualIncome}`;
}
}
class PersonBuilder {
constructor(person) {
if (person instanceof Person) {
this.person = person;
} else {
this.person = new Person();
}
}
get lives() {
return new PersonAddressBuilder(this.person);
}
get works() {
return new PersonJobBuilder(this.person);
}
build() {
return this.person;
}
}
class PersonJobBuilder extends PersonBuilder {
constructor(person) {
super(person);
}
at(companyName) {
this.person.companyName = companyName;
return this;
}
asA(position) {
this.person.position = position;
return this;
}
earning(annualIncome) {
this.person.annualIncome = annualIncome;
return this;
}
}
class PersonAddressBuilder extends PersonBuilder {
constructor(person) {
super(person);
}
at(streetAddress) {
this.person.streetAddress = streetAddress;
return this;
}
withPostcode(postcode) {
this.person.postcode = postcode;
return this;
}
inCity(city) {
this.person.city = city;
return this;
}
}
const personBuilder = new PersonBuilder();
const person = personBuilder
.lives
.at("123 London Road")
.inCity("London")
.withPostcode("SW12BC")
.works
.at("Fabrikam")
.asA("Engineer")
.earning(123000)
.build();
const person2 = new PersonBuilder().build();
console.log(person);
console.log(person2);