Fluent interface и Delphi

в 14:21, , рубрики: Delphi, fluent interface, метки: ,

Текучий интерфейс (Fluent interface) — совсем молодая методика, даже скорее паттерн проектирования, получивший популярность и широкое распространение среди кодеров Java, C#, PHP.
В большинстве методик «хорошего кода» лежит разряжение текста кода (висячие строки, пробелы, отступы, etc) и это очень здорово, но иногда это превращается в сущий ад. Пробежка скролом по коду, запоминание цепочки вызова метода, вечная дилемма между длинным методом и читабельностью, etc.
Но решение есть — Текучий интерфейс! Теперь и на Delphi!

Так что же такое текучий интерфейс?

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

CreateFluentBinaryWriter(Stream)
  .WriteString('active')
  .WriteByte(130);

Реализация

Интерфейс выглядит элементарно — так:

IFluentBinaryWriter = interface
  function WriteByte(Value: Byte): IFluentBinaryWriter; 
  function WriteString(Value: string): IFluentBinaryWriter; 
end;

Вспомогательная функция создания класса, реализующего интерфейс, выглядит очень просто — так:

function CreateFluentBinaryWriter(AStream: TStream): IFluentBinaryWriter;
begin
  Result := TFluentBinaryWriter.Create(AStream);
end;

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

Как например функция WriteString записывает строку в поток (TBytesStream), и возвращает экземпляр класса вызвавшего эту функцию

function TFluentBinaryWriter.WriteString(Value: string): IFluentBinaryWriter;
begin 
  fBinaryWriter.Write(Value); // TBinaryWriter
  Result := Self; 
end;

Вот и всё! Собственно на этом можно было закончить, но есть одна очень интересная реализация!

Вариант два — посложнее

CreateFluentStringWriter(Stream)
  ['Привет ']
  ['Мир']
  ['!'];

Здесь мы пойдем на небольшую хитрость. Объявим свойство Attrib

property Attrib[Value: string]: IFluentStringWriter read AddString; default;

и в функции AddString мы запишем запрашиваемую строку в поток и вернём в качестве результата экземпляр класса вызвавшего эту функцию

function TFluentValueWriter.AddString(Value: string): IFluentValueWriter;
begin
  fBinaryWriter.Write(Value); // TBinaryWriter
  Result := Self;
end;

PS

Использование текучего интерфейса весьма широко, и вкупе с анонимными процедурами можно достичь очень компактного и самодокументируемого кода!

Автор: VLT

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js