Класс ES6 и экземпляр класса как параметр в конструкторе

классу A нужен экземпляр класса B. Должен ли я создать экземпляр B внутри конструктора A или создать экземпляр, в котором инициируется класс A, и передать экземпляр конструктору A?

План А:

class A { constructor() { this.b = new B(); } }

План B:

const b = new B();

class A() { 
    constructor(b) { 
        this.b = b; 
    }
}

const a = new A(b);

В идеале класс A должен создать экземпляр класса B внутри, если он этого требует. Коду, который использует класс A, не нужно знать, какая зависимость нужна этому классу.

Terry 16.08.2018 09:01

Я бы сказал план Б, так как он будет полезен для управления инъекциями зависимостей

Ankit Agarwal 16.08.2018 09:02

план Б очень полезен]

Jasmin Mistry 16.08.2018 09:05

Как было сказано, это всего лишь вопрос мнения. Я действительно зависит от того, как эти классы будут использоваться. Например, будет ли когда-нибудь полезно для вызывающего A передавать что-либо, кроме B? Нужно ли им вообще взаимодействовать с B?

Mark 16.08.2018 09:09

На этот вопрос невозможно ответить должным образом, потому что вы спрашиваете о чем-то, где подход будет полностью зависеть от контекста.

Marty 16.08.2018 09:11

Так что, пожалуйста, вы можете привести примеры с разными контекстами и сценариями.

user3462947 16.08.2018 09:18
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
6
81
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ваш план Б - определенно лучший подход, потому что он делает ваш class A более гибким и устраняет зависимости от того, как работает class B.

Ответ принят как подходящий

План А подходит, если

  • Класс B не следует заменять на класс C в будущем.

  • Класс B не использует какую-либо внешнюю зависимость, такую ​​как ajax, база данных или что-то еще.

ИЛИ

  • Ваше приложение является подтверждением концепции, или вы действительно ограничены во времени

План Б хорош во всех остальных случаях.

Это даст вам гибкость для изменения поведения вашего класса A на лету, предоставит большую универсальность, поможет с тестированием, высмеивая эту зависимость.

Итак, я бы сказал, что план А - о простоте, план Б - о гибкости и тестировании. Выбирайте то, что вам нужно в каждом конкретном случае

Надеюсь это поможет.

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

Последняя стратегия внедрения зависимостей класса гораздо более гибкая. Это более очевидно в типизированном языке, где вы можете четко определить абстракции классов или интерфейсы, которые описывают, как объект «выглядит», а не фактическую реализацию, например с TypeScript:

class Process {
  private storage: StorageInterface;

  constructor(storage: StorageInterface) {
    this.storage = storage;
  }
}

interface StorageInterface {
  store(data: any): Promise<void>;
}

Здесь ясно, что Process ожидает экземпляр чего-то, что предоставляет функцию store, но не заботится о том, как выглядит фактическая реализация - это остается на усмотрение класса, реализующего StorageInterface:

class PostgresStorage implements StorageInterface {
  public async store(data: any): Promise<void> {
    // do some postgres query
  }
}

class FilesystemStorage implements StorageInterface {
  public async store(data: any): Promise<void> {
    // store in the filesystem
  }
}

Теперь у нас есть полная гибкость в отношении того, какой тип «хранилища» мы хотим использовать для экземпляра Process, а не управление самим хранилищем, которое он может использовать, возможность создавать бесконечные типы хранилищ без изменения остальной части кодовой базы и многое другое. ясность относительно того, с чем взаимодействует Process.

// A process that stores something in a Postgres instance.
const processA: Process = new Process(new PostgresStorage());

// A process that stores something on the filesystem.
const processB: Process = new Process(new FilesystemStorage());

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

https://en.wikipedia.org/wiki/Composition_over_inheritance

Другие вопросы по теме