Как корректно реализовать код?

Рейтинг: 0Ответов: 1Опубликовано: 11.01.2023

Нужно написать программу, рассчитывающую стоимость и калорийность гамбургера. Использовать ООП подход. Есть пример работы кода:

// маленький гамбургер c начинкой с сыром //
var hamburger = new Hamburger(Hamburger .SIZE_SMALL, Hamburger.STUFFING_CHEESE);

// добавка майонеза
hamburger.addTopping(Hamburger.TOPPING_MAYO);

// спрашиваем сколько калорий
console.log('Calories: ' + hamburger.calculate ());

// тут я передумал и решил добавить еще приправу
hamburger.addTopping(Hamburger .TOPPING_SAUCE);

// Сколько теперь стоит?
console.log('Price with sauce:' + hamburger.calculatePrice());

Пробовал написать сам не очень понимаю как реализовать и рассчитывать цену и калории. Прикрепляю пример моего кода то что пытался сам написать.

class Hamburger {
    constructor() {}
    static SIZE_SMALL (price,calories) {};
    static SIZE_HUGE (price,calories) {};
    static STUFFING_CHEESE (price,calories) {};
    static STUFFING_SALAD (price,calories) {};
    static STUFFING_POTATOE (price,calories) {};
    static TOPPING_SAUCE (price,calories) {};
    static TOPPING_MAYO (price,calories) {};
    addTopping (TOPPING_MAYO) {};
    calculate () {

    }
    calculatePrice () {

    }

}
//_______Размеры гамбургеров_______//
Hamburger.SIZE_SMALL(50,20);
Hamburger.SIZE_HUGE(100,40);

//_______Начинки гамбургеров_______//
Hamburger.STUFFING_CHEESE(10,20);
Hamburger.STUFFING_SALAD(20,5);
Hamburger.STUFFING_POTATOE(15,10);

//_______Добавки к гамбургерам_______//
Hamburger.TOPPING_SAUCE(15,0);
Hamburger.TOPPING_MAYO(20,5);

// маленький гамбургер с начинкой з сыру //
let hamburger = new Hamburger(Hamburger.SIZE_SMALL, Hamburger.STUFFING_CHEESE);

// добавка майонеза
hamburger.addTopping(Hamburger.TOPPING_MAYO);

// спрашиваем сколько калорий
console.log('Calories: ' + hamburger.calculate ());

// тут я передумал и решил добавить еще приправу
hamburger.addTopping(Hamburger .TOPPING_SAUCE);

// Сколько теперь стоит?
console.log('Price with sauce:' + hamburger.calculatePrice());

Ответы

▲ 1Принят

Я бы сделал так:

class CompositionElement {
  constructor(price, calories) {
    this.price = price;
    this.calories = calories;
  }
}

class Hamburger {
  static #SIZE_SMALL = new CompositionElement(50, 20);
  static #SIZE_HUGE = new CompositionElement(100, 40);
  static #STUFFING_CHEESE = new CompositionElement(10, 20);
  static #STUFFING_SALAD = new CompositionElement(20, 5);
  static #STUFFING_POTATOE = new CompositionElement(15, 10);
  static #TOPPING_SAUCE = new CompositionElement(15, 0);
  static #TOPPING_MAYO = new CompositionElement(20, 5);

  static get SIZE_SMALL () { return Hamburger.#SIZE_SMALL};
  static get SIZE_HUGE () { return Hamburger.#SIZE_HUGE};
  static get STUFFING_CHEESE () { return Hamburger.#STUFFING_CHEESE};
  static get STUFFING_SALAD () { return Hamburger.#STUFFING_SALAD};
  static get STUFFING_POTATOE () { return Hamburger.#STUFFING_POTATOE};
  static get TOPPING_SAUCE () { return Hamburger.#TOPPING_SAUCE};
  static get TOPPING_MAYO () { return Hamburger.#TOPPING_MAYO};

  #size = null;
  #stuff = null;
  #ingredients = [];

  constructor(...args) {
    args.forEach(this.#changeComposition.bind(this));
  }

  #changeComposition(element) {
    switch (element) {
      case Hamburger.#SIZE_SMALL:
      case Hamburger.#SIZE_HUGE:
        this.#changeSize(element);
        break;
      case Hamburger.#STUFFING_CHEESE:
      case Hamburger.#STUFFING_SALAD:
      case Hamburger.#STUFFING_POTATOE:
        this.#changeStuff(element);
        break;
      default:
        this.addTopping(element);
    }
  }

  #changeSize(size) {
    this.#size = size;
  }

  #changeStuff(stuff) {
    this.#stuff = stuff;
  }

  addTopping(topping) {
    this.#ingredients.push(topping);
  }

  calculate() {
    return this.#size.calories +
      this.#stuff.calories +
      this.#ingredients.reduce((totalCalories, ingredient) => totalCalories + ingredient.calories, 0);
  }

  calculatePrice() {
    return this.#size.price +
      this.#stuff.price +
      this.#ingredients.reduce((totalPrice, ingredient) => totalPrice + ingredient.price, 0);
  }

}

// маленький гамбургер с начинкой з сыру //
let hamburger = new Hamburger(Hamburger.SIZE_SMALL, Hamburger.STUFFING_CHEESE);

// добавка майонеза
hamburger.addTopping(Hamburger.TOPPING_MAYO);

// спрашиваем сколько калорий
console.log('Calories: ' + hamburger.calculate ());

// тут я передумал и решил добавить еще приправу
hamburger.addTopping(Hamburger .TOPPING_SAUCE);

// Сколько теперь стоит?
console.log('Price with sauce:' + hamburger.calculatePrice());

Ответ на вопрос из комментария:

Для чего мы используем get и почему возвращем Hamburger.#Private_Static_Field

В поле static #Private_Static_Field я храню созданный экземпляр класса CompositionElement, в приватном статическом поле. Это нужно по нескольким причинам:

  1. Мы сохранем экземпляр класса и нам не нужно его пересоздавать каждый раз

  2. Можно использовать строгое сравнение при передачи этого объекта в любой метода класса. Например это используется в switch, чтобы понять что именно передали нам в конструктор. Если бы я возвращал каждый раз new CompositionElement(...), то сравнение было бы невозмжно, т.к. у каждого была своя ссылка

  3. Поле приватное, чтобы к нему не было доступа извне класса

  4. Поле статическое чтобы статические методы могли к ниму обращаться

Я использую get модификатор доступа чтобы нельзя было изменить извне. Простой пример как это помогает:

class WithoutGetModificator {
  static Field = 'field';
}

console.log(WithoutGetModificator.Field);

WithoutGetModificator.Field = 'modified field';

console.log(WithoutGetModificator.Field);

class WithGetModificator {
  static get Field() {return 'field'};
}

console.log(WithGetModificator.Field);

WithGetModificator.Field = 'modified field';

console.log(WithGetModificator.Field);