Применение полиморфизма подтипов не убирает условные конструкции полностью (кроме некоторых случаев диспетчеризации, например по ключу или по имени файла). Чаще условная конструкция остается одна, только на уровне выбора подходящей реализации, а вот затем эта реализация используется внутри полиморфной функции прямым способом без условий. В прошлом уроке мы рассмотрели пример функции, которая выбирает необходимую реализацию стратегии на основе возраста пользователя и возвращает ее наружу.
const chooseCostInsuranceStrategy = (user) => {
if (user.getAge() < 18) {
return new LessThan18();
} else if (/* ... */) {
// some code
}
}
Функция, которая выбирает нужный класс, создает объект и возвращает его наружу, называется фабрикой (более точно фабричным методом). Громкое имя для очень простой штуки. Фабрика может быть реализована любым способом, включая все, что разбиралось в этом курсе.
В общем случае фабрикой называют все подряд, что создает объект или коллекции объектов. Причем не обязательно разных классов, класс может быть и один, но сам процесс создания включает в себя какие-то предварительные вычисления. В реальных проектах фабрики могут быть достаточно большими.
Фабрики часто реализуются как классы с одним статическим методом — factory
. Обычно сами фабрики объектами не делают, так как это не абстракция данных, а подменять их смысла нет, иначе получится подмена подменятора.
export default class {
static factory(/* параметры */) {
// код фабрики
}
}
Диспетчеризация класса
JavaScript позволяет создавать объекты, используя ссылку на класс
const className = Application;
const app = new className();
Такой синтаксис открывает широкий простор для диспетчеризации. Например, в некоторых ситуациях получится уйти от условных конструкций вообще:
import ManagerPolicy from './policies/ManagerPolicy.js';
import WorkerPolicy from './policies/WorkerPolicy.js';
// Policy — обычно это имя используют для авторизации, то есть системы проверки прав доступа
const mapping = {
manager: ManagerPolicy,
worker: WorkerPolicy,
};
const getUserPolicy = (user) => {
const className = mapping[user.getType()];
return new className();
};
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.