Seguindo na idéia de interfaces fluentes (expliquei o que elas são aqui), vou fecjar o assunto de builder. Se você não leu o outro post sobre o assunto, veja-o aqui.

Já sabemos como utilizar um builder assim:

            var item3 = new CatalogItemBuilder()
                 .Named("iPhone")
                 .ManufacturedBy(m => m.Named("Apple"))
                 .ForProduct(p => p.Number = "AA1687")
                 .Build();
            category.Categorize(item3);

Como fazer para chegar na construção baseada em lambas? Afinal, esse é o objetivo final. Queremos isso:

            var category = new Category();
            category.Categorize(item =>item.Named("iPhone")
                .ManufacturedBy(manufacturer =>
                    manufacturer.Named("Apple"))
                    .ForProduct(product =>
                        product.Numbered("AA1687")));

Fácil. Note que nesta segunda construção o método Categorize recebe uma lambda, que na verdade é um delegate, mais precisamente um Action<CatalogItemBuilder>. Basta criar então este método:

        public void Categorize(Action<CatalogItemBuilder> buildUsing)
        {
            var catalogItemBuilder = new CatalogItemBuilder();
            buildUsing(catalogItemBuilder);
            var item = catalogItemBuilder.Build();
            Categorize(item);
        }

E então a construção com Lambdas, a partir da categoria, já fica possível. Tudo baseado em inferência de tipos.

Note que o método utiliza o Action<CatalogItemBuilder>, passando para ele a ação que recebeu (as lambdas do segundo exemplo de código). Com isso, o builder é “populado” com valores. Aí ele utiliza o método Build para construir o item, e retorna-o. Simples assim.

Eu havia falado recentemente que o F# influenciou muito o C#. Está muito claro que esse tipo de construção usadas em interfaces fluentes está agarrada nos conceitos de programação funcional. É descarado (no bom sentido) o uso das funções como conceitos de primeiro nível. Notem que em todos estes casos, estamos passando funções, em forma de delegates, como argumentos aos métodos. Um delegate nada mais é que uma função em forma de objeto.

O projeto todo, com outros exemplos de chamada, pode ser baixado aqui. São 2 arquivos úteis em 5kb.

(E o Java Community Process (JCP) está a séculos decidindo se aprova ou não o uso de delegates no Java. Enquanto eles não aprovarem, isso não vai ser possível, ou, no mínimo, não será tão simples.)

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.