Как можно использовать шаблон функциональных опций для построения более точных определений классов
Шаблон функциональных опций хорошо зарекомендовал себя в сообществе Golang, и я был особенно впечатлен при изучении языка. Он продуман, но прост в реализации и прост в использовании.
Так что же на самом деле представляет собой шаблон функциональных опций и как мы можем использовать его для создания классов в Typescript? Давайте сначала исследуем некоторые точки соприкосновения и разберемся, как современные шаблоны построения классов в некоторых областях не оправдывают ожиданий.
Ниже приведен типичный шаблон для создания объекта класса, в котором каждое свойство задается отдельным аргументом конструктора.
const myHouse = new House(5, 2, 'wood')
Этот шаблон подходит для простых объектов, но быстро перестает работать, если:
- Ваш класс содержит много свойств
- В вашем классе есть как необязательные, так и обязательные свойства.
- Вам необходимо реализовать проверку устанавливаемых значений свойств.
Любой из вышеперечисленных случаев вызовет раздувание вашего конструктора, будь то количество аргументов, которые он принимает, или добавленная логика для проверки аргументов, установки значений по умолчанию и выполнения проверки. Результат будет неаккуратным.
Как видите, количество аргументов утомительно, равно как и необходимость добавлять операторы «if» для проверки каждого переданного аргумента. И это даже не касается того, если несколько аргументов являются необязательными, и установки значений по умолчанию!
Объект «Параметры» или «Конфигурация»
Это, вероятно, наиболее распространенный шаблон, используемый для решения описанных выше проблем. Он состоит из набора и передачи одного объекта параметров в конструктор, который может содержать все свойства объекта, а также свойства объекта конфигурации. Это делает хорошую работу по сокращению аргументов конструктора до одного и решает проблему наличия комбинации необязательных и обязательных свойств, поскольку они могут быть напечатаны соответствующим образом в определении объекта конфигурации.
const myHouse = new House({ floors: 2, rooms: 5, material: 'wood', })
Но этот шаблон на самом деле не решает ни неудобства установки значений по умолчанию, ни необходимость раздувания конструкторов if-операторов для проверки установленных значений свойств. Вдобавок повторяемость определения как класса, так и интерфейса опций с типичным зеркальным отображением далеко не идеальна.
Как вы можете видеть в приведенном выше примере, это может быстро выйти из-под контроля.
Функциональные параметры машинописного текста
Ниже вы найдете реализацию шаблона функциональных опций с использованием методов статического класса в качестве конструкторов опций.
const myHouse = new House( House.WithRooms(5), House.WithFloors(2), House.WithMaterial('wood') )
Этот шаблон определенно более подробен, когда дело доходит до реализации, однако он имеет несколько преимуществ по сравнению с ранее описанными шаблонами:
- Само определение конструктора очень простое. Размер его определения аргументов невелик и не увеличивается с увеличением количества добавленных свойств класса.
- Установка значений по умолчанию проста, без необходимости в операторах if, проверяющих необязательность переданных аргументов. Значения свойств по умолчанию устанавливаются непосредственно для объекта, при этом изменение этих свойств по умолчанию является необязательным для вызывающего объекта.
- Проверка каждого свойства содержится в его собственном контексте вместо того, чтобы раздувать конструктор операторами if. Дополнительным бонусом является то, что, присущая этому шаблону, проверка выполняется только в том случае, если для свойства установлено значение, отличное от значения по умолчанию.
Проницательный читатель также заметит, что вы можете воспользоваться преимуществами конструкторов опций, если вы склонны писать функции установщика классов, что, безусловно, может сэкономить вам некоторое время.
class House { ... public setRooms(roomCount: number): void { House.WithRooms(roomCount)(this) } }
Заключение
Шаблон «Функциональные параметры» возник в Golang в значительной степени из-за комбинации специфических особенностей самого языка и потребности в более гибком построении объектов в результате этих языковых функций. Однако этот шаблон не является специфическим для Golang и явно имеет преимущества для построения объектов на других языках.
Использование шаблона функциональных опций для определений классов Typescript может помочь «подготовить» ваши классы к будущему, сделав их более понятными и более простыми для работы, если и когда они со временем станут более сложными.
Этот шаблон также может помочь вам написать конструкторы классов async:
Как написать конструктор асинхронного класса в Typescript / Javascript
Без использования стандартных шаблонов« init или builder medium.com»
Удачного кодирования!