...

пятница, 23 августа 2013 г.

[Из песочницы] Fluent interface и Delphi

Текучий интерфейс (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



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

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends: 'You Say What You Like, Because They Like What You Say' - http://www.medialens.org/index.php/alerts/alert-archive/alerts-2013/731-you-say-what-you-like-because-they-like-what-you-say.html


Комментариев нет:

Отправить комментарий