Значения объекта по умолчанию и варианты использования шаблона построителя

Объект Значения по умолчанию

В этой статье я продолжу рассказывать о шаблонах проектирования. Сегодняшний урок посвящен шаблону стратегии строителя. Это может быть очень полезно для поддержания чистого кода. Есть несколько советов и приемов, которые могут помочь вам идентифицировать и использовать шаблон построителя.

let  user = {
  name: "Tim", 
  lastName: "Benoi",
  address: {
    street: "Picadilly", 
    post: "212 14"
  }, 
  telefon: [
    {
      homeNumber: "761222122"
    },
    {
      workNumber: "761222122"
    }
  ]
}

Мы можем получить доступ к параметрам объекта через точку, деструктурируя объект, как обсуждалось в предыдущем посте. Если вы хотите узнать об этом подробнее, перейдите по ссылке. здесь =› https://webdevs.se/admin/content/posts/edit/18

let { name, lastName, address: { street, post }, telefon} = user

Однако давайте представим сценарий, в котором мы получаем доступ к переменным, которые не определены в пользовательском объекте.

let { name, lastName, address: { street, post }, telefon, companyName, position} = user

как видите, мы присвоили переменные companyName и position объекту пользователя. Однако пользовательский объект не имеет этих переменных. В результате javascript установит значения по умолчанию undefined.

// companyName => undefined, position => undefined

Здесь появляются значения по умолчанию.

let { name, lastName, address: { street, post }, telefon, companyName = "Invajo", position = "developer"} = user

//console.log(company) companyName => Invajo, console.log(position) position => developer

// we encapsulate work related information into an object

let { name, lastName, address: { street, post }, telefon, work = { name:"Invajo", position:"developer" }} = user

// => console.log(work) {name: "Invajo", position: "developer"}

Значения по умолчанию можно использовать в функциях, и существует множество других полезных сценариев использования, однако это выходит за рамки данной статьи. Позже мы увидим, как эта техника может быть полезна при построении шаблона строителя.

Бизнес-кейс: Производитель автомобилей

Давайте представим, что мы — производитель автомобилей, который продает разные автомобили и позволяет своим клиентам модифицировать определенные части автомобиля. Например, двигатель, кондиционер, автоматический переключатель, автопилот и т. д. Для этого мы сначала создаем автомобиль с базовой конфигурацией, а затем пишем логику, позволяющую добавлять дополнительные функции.

class CarBuilder {
  constructor(engine, fuelType, autopilot, navigation) {
    this.engine = engine
    this.fuelType = fuelType
    this.autopilot = autopilot
    this.navigation = navigation
  }
}

// let define our customer engine

class Engine {
  constructor(model, horsePower) {
    this.model = model
    this.horsePower = horsePower
  }
}

// our default engine
class defautlEngine {
  constructor() {
    this.model = "F100"
    this.horsePower = 120
  }
}

// let's assume our customer made choice of only

let engine = new Engine("F130", 390)
let customerCar = new CarBuilder(engine, "petrol", true, true)

// console.log(customerCar)
// => Car; {engine: {horsePower: 390, model: "F130"}, fuelType: "petrol", autopilot: true, navigation: true}

В этом случае наш клиент выбирает все четыре варианта комплектации, которые мы должны были предложить, теперь что произойдет, если наш клиент захочет купить автомобиль только с двумя комплектациями. Как видите, наш первый заполнитель — это двигатель, поэтому мы должны передать значение undefined для двигателя, автопилота и навигации.

let customerCar1 = new Car(new Engine("F100", 120), "petrol", false, true)
// engine with model F130 and horse power 120 is our default engine
// console.log(customerCar1) => 
Car;{ 
engine:
  { 
    horsePower:120, 
    model: "F100"
  }, 
fuelType: "petrol", 
autopilot: false, 
navigation: true}

Как вы можете видеть, было бы трудно продолжать эту текущую логику, представьте, что у нас есть 100 конфигураций, и мы должны присвоить правильные значения в зависимости от того, как переменные размещены в нашем конструкторе класса. Здесь вступает в действие шаблон конструктора. Мы можем динамически строить автомобиль на основе входных данных. Давайте сначала определим наш класс автомобиля по умолчанию

class defaultEngine {
  constructor() {
    this.model = "F100"
    this.horsePower = 120
  }
}

// engine builder
class engineBuilder {
  constructor() {
    this.engine = new defaultEngine()
  }
  
  setModel(model) {
    this.engine.model = model
    return this
  }
  
  sethorsePower(hp) {
    this.engine.horsePower = hp
    return this
  }
  
  buildEngine() {
    return this.engine
  }
}

class defaultCar {
  constructor() {
    // we are building simple engine
    this.engine = new engineBuilder()
    this.fuelType = "diesel"
    this.autopilot = false
    this.navigation = false
    
  }
}

class carBuilder {
  constructor() {
    this.car = new defaultCar()
  }
  
  setEngine(engine) {
    this.car.engine = engine
    return this
  }
  
  setPetrol(fuelType) {
    this.car.fuelType = fuelType
    return this
  }
  
  setAutoPilot(autopilot) {
    this.car.autopilot = autopilot
    return this
  }
  
  setNavigation(navigation) {
    this.car.navigation = navigation
    return this
  }
  
  setAirconditoner(airConditioner) {
    this.car.airConditioner = airConditioner
    return this
  }
  
  setAutomaticBreak(autobreak) {
    this.car.autobreak = autobreak
    return this
  }
  
  buildCar() {
    return this.car
  }
  
}

Наша установка готова, давайте на самом деле инициализируем простую машину с простым двигателем.

let defaultEngine = new engineBuilder().buildEngine()

// => defaultEngine {model: "F100", horsePower: 120}
let simpleCa1 = new carBuilder().setEngine(defaultEngine).buildCar()

// => defaultCar {engine: defaultEngine, fuelType: "diesel", autopilot: false, navigation: false}

// let configure our engine and car

let f130Engine = new engineBuilder().setModel("F130").sethorsePower(450).buildEngine()
let f140car = new carBuilder()
                 .setEngine(f130engine)
                 .setAirconditoner(true).
                 .setFuelType("petrol")
                 .setNavigation(true).
                 .setAutoPilot(true).
                 .setAutomaticBreak(true)
                 .buildCar()
// => 
/*
defaultCar {engine: defaultEngine, fuelType: "diesel", autopilot: true, navigation: true, airConditioner: true, …}
  airConditioner: true
  autobreak: true
  autopilot: true
    engine: defaultEngine
      horsePower: 120
      model: "F130"
  fuelType: "petrol"
  navigation: true

*/

Давайте повторим тот же шаблон, используя значения по умолчанию.

// same things with default values

class Engine {
  constructor({ model="F120", horsePower=120 } = {}) {
    this.model = model
    this.horsePower = horsePower
  }
}

class Car {
  constructor(engine, { fuelType="diesel", autopilot=false, navigation=false } = {}) {
    // we are building simple engine
    this.engine = engine
    this.fuelType = fuelType
    this.autopilot = autopilot
    this.navigation = navigation
  }
}

// let build f13o engine car with diesel and navigation
// accesssing parameters with object destructuring

let f130Engine = new Engine({ model: "F130"})

// console.log(f130Engine) => { model: "F130", horsePower: 120}

let dieselCar = new Car(f130Engine, { navigation: true })

// console.log(dieselCar) => 
/*
Car { 
engine: Engine, 
fuelType: "diesel", 
autopilot: false, 
navigation: true
}
autopilot: false
engine: Engine
horsePower: 120
model: "F130"
fuelType: "diesel"
navigation: true

*/

Это выглядит просто с деструктуризацией объекта и техникой значений по умолчанию. Я надеюсь, что это принесет пользу для вас.