Подтвердить что ты не робот

Свободные интерфейсы - Цепочка метода

Цепочка метода - это единственный способ, с помощью которого я знаю, создавать свободные интерфейсы.

Вот пример в С#:

John john = new JohnBuilder()
    .AddSmartCode("c#")
    .WithfluentInterface("Please")
    .ButHow("Dunno");

Assert.IsNotNull(john);

  [Test]
    public void Should_Assign_Due_Date_With_7DayTermsVia_Invoice_Builder()
    {
        DateTime now = DateTime.Now;

        IInvoice invoice = new InvoiceBuilder()
            .IssuedOn(now)
            .WithInvoiceNumber(40)
            .WithPaymentTerms(PaymentTerms.SevenDays)
            .Generate();

        Assert.IsTrue(invoice.DateDue == now.AddDays(7));
    }

Итак, как другие создают свободные интерфейсы. Как вы его создаете? Какой язык/платформа/технология необходимы?

4b9b3361

Ответ 1

Вы можете создать свободный интерфейс в любой версии .NET или любом другом языке, который является объектно-ориентированным. Все, что вам нужно сделать, это создать объект, методы которого всегда возвращают сам объект.

Например, в С#:

public class JohnBuilder
{
    public JohnBuilder AddSmartCode(string s)
    {
        // do something
        return this;
    }

    public JohnBuilder WithfluentInterface(string s)
    {
        // do something
        return this;
    }

    public JohnBuilder ButHow(string s)
    {
        // do something
        return this;
    }
}

Использование:

John = new JohnBuilder()
    .AddSmartCode("c#")
    .WithfluentInterface("Please")
    .ButHow("Dunno");

Ответ 2

Основная идея создания свободного интерфейса - одна из читабельности - кто-то, читающий код, должен быть в состоянии понять, что достигается, не вникая в реализацию, чтобы уточнить детали.

В современных OO-языках, таких как С#, VB.NET и Java, цепочка методов является одним из способов достижения этой цели, но это не единственный метод - два других - это классы factory и именованные параметры.

Отметим также, что эти методы не являются взаимоисключающими - цель состоит в том, чтобы максимизировать читабельность кода, а не чистоту подхода.

Цепочка методов

Ключевое понимание цепочки методов заключается в том, чтобы никогда не иметь метод, который возвращает void, но всегда возвращать некоторый объект или, чаще, некоторый интерфейс, который позволяет делать дальнейшие вызовы.

Вам необязательно возвращать тот же объект, на который был вызван метод, то есть вам не всегда нужно "возвращать это".

Одним из полезных методов проектирования является создание внутреннего класса - я всегда суффикс их с помощью выражения "Expression", который предоставляет свободный API, позволяющий конфигурировать другой класс.

Это имеет два преимущества: он поддерживает свободный API в одном месте, изолированный от основной функциональности класса, и (поскольку он является внутренним классом), он может возиться с внутренностями основного класса способами, которые другие классы не могут.

Вы можете использовать серию интерфейсов, чтобы контролировать, какие методы доступны разработчику в данный момент времени.

Factory Классы

Иногда вы хотите создать ряд связанных объектов - примеры включают API-интерфейс NHibernate, ограничения ожидания Rhino.Mocks и новый синтаксис NUnit 2.4.

В обоих случаях у вас есть фактические объекты, которые вы храните, но чтобы упростить их создание, существуют классы factory, предоставляющие статические методы для создания требуемых экземпляров.

Например, в NUnit 2.4 вы можете написать:

Assert.That( result, Is.EqualTo(4));

Класс "Is" - это статический класс, полный методов factory, которые создают ограничения для оценки с помощью NUnit.

Фактически, чтобы допускать ошибки округления и другую неточность чисел с плавающей запятой, вы можете указать точность для теста:

Assert.That( result, Is.EqualTo(4.0).Within(0.01));

(Предварительные извинения - мой синтаксис может быть отключен.)

Именованные параметры

В языках, поддерживающих их (включая Smalltalk и С# 4.0), именованные параметры предоставляют возможность включить дополнительный "синтаксис" в вызов метода, улучшая читаемость.

Рассмотрим гипотетический метод Save(), который принимает имя файла и разрешения для применения к файлу после сохранения:

myDocument.Save("sampleFile.txt", FilePermissions.ReadOnly);

с именованными параметрами, этот метод может выглядеть следующим образом:

myDocument.Save(file:"SampleFile.txt", permissions:FilePermissions.ReadOnly);

или, более свободно:

myDocument.Save(toFile:"SampleFile.txt", withPermissions:FilePermissions.ReadOnly);

Ответ 3

AFAIK, термин "свободный интерфейс" не указывает конкретную технологию или структуру, а скорее шаблон проектирования. У Wikipedia есть обширный пример свободного интерфейса в C♯.

В простом методе setter вы не возвращаете void, а this. Таким образом, вы можете связать все операторы этого объекта, которые ведут себя так. Вот краткий пример, основанный на вашем исходном вопросе:

public class JohnBuilder
{
    private IList<string> languages = new List<string>();
    private IList<string> fluentInterfaces = new List<string>();
    private string butHow = string.Empty;

    public JohnBuilder AddSmartCode(string language)
    {
        this.languages.Add(language);
        return this;
    }

    public JohnBuilder WithFluentInterface(string fluentInterface)
    {
        this.fluentInterfaces.Add(fluentInterface);
        return this;
    }

    public JohnBuilder ButHow(string butHow)
    {
        this.butHow = butHow;
        return this;
    }
}

public static class MyProgram
{
    public static void Main(string[] args)
    {
        JohnBuilder johnBuilder = new JohnBuilder().AddSmartCode("c#").WithFluentInterface("Please").ButHow("Dunno");
    }
}

Ответ 4

Когда-то назад у меня были те же сомнения, что и сейчас. Я провел некоторое исследование, и теперь я пишу серию сообщений в блогах об технологиях разработки плавного интерфейса.

Проверьте это:

Рекомендации по свободному дизайну интерфейса в части С# 1

У меня есть раздел о Chaining X Nesting, который может быть вам интересен.

В следующих сообщениях я расскажу об этом более подробно.

С уважением,

Андре Вианна

Ответ 5

Свободный интерфейс достигается в объектно-ориентированном программировании, всегда возвращаясь из ваших методов к тому же интерфейсу, который содержит этот метод. Следовательно, вы можете добиться этого эффекта в java, javascript и других ваших любимых объектно-ориентированных языках, независимо от версии.

Я нашел эту технику проще всего благодаря использованию интерфейсов:

public interface IFoo
{
    IFoo SetBar(string s);
    IFoo DoStuff();
    IFoo SetColor(Color c);
}

Таким образом, любой конкретный класс, реализующий интерфейс, получает плавные возможности цепочки методов. FWIW.. Я написал код выше в С# 1.1

Вы найдете эту технику, замусоренную во всем API jQuery

Ответ 6

Вот как я построил так называемые беглые интерфейсы или мой единственный форин в нем

Tokenizer<Bid> tkn = new Tokenizer<Bid>();
tkn.Add(Token.LambdaToken<Bid>("<YourFullName>", b => Util.CurrentUser.FullName))
    .Add(Token.LambdaToken<Bid>("<WalkthroughDate>",
          b => b.WalkThroughDate.ToShortDateString()))
    .Add(Token.LambdaToken<Bid>("<ContactFullName>", b => b.Contact.FullName))
    .Cache("Bid")
    .SetPattern(@"<\w+>");

Мой пример требует .net 3.5, но это только причина моей лямбды. Как заметил Брэд, вы можете сделать это в любой версии .net. Хотя я думаю, что лямбда делает для этого более интересные возможности.

======

Другими хорошими примерами являются API-интерфейс nHibernate Criteria, также существует свободное расширение nhibernate для настройки nhibernate, но я никогда не использовал его

Ответ 7

Несколько соображений приходят на ум, которые возможны в .Net 3.5/С# 3.0:

  • Если объект не реализует свободный интерфейс, вы можете использовать методы расширения для цепочки вызовов.

  • Возможно, вы сможете использовать инициализацию объекта для симуляции свободно, но это работает только во время создания экземпляра и будет работать только для методов с одним аргументом (где свойство является только сеттером). Это кажется мне хакированным, но там оно.

Лично я не вижу ничего плохого в использовании цепочки функций, если вы реализуете объект-строитель. Если объект строителя имеет методы цепочки, он сохраняет объект, который вы создаете чистым. Просто мысль.

Ответ 8

Я нашел способ выполнять цепочки полиморфных методов на свободных интерфейсах с безопасностью типа, которые были соблюдены во время компиляции с использованием общих сборщиков и общих методов расширения.

http://withasmiletomeltathousandhearts.wordpress.com/2009/02/16/fluent-interfaces-constraints-at-compile-time/

Методы расширения - это круто:)

Ответ 9

Динамическое ключевое слово в С# 4.0 позволит писать динамические стилисты. Взгляните на статью о конструкции объекта JSON.