33

私が知っている流暢なインターフェイスを構築する方法は、メソッド チェーンだけです。

C# での例を次に示します。

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));
    }

では、他の人はどのようにして流暢なインターフェースを作成しているのでしょうか。どのように作成しますか?どの言語/プラットフォーム/テクノロジーが必要ですか?

4

8 に答える 8

51

流暢なインターフェイスを構築する背後にある核となる考え方は、読みやすさです。コードを読む人は、詳細を明確にするために実装を掘り下げなくても、達成されていることを理解できる必要があります。

C#、VB.NET、Java などの最新の OO 言語では、メソッド チェーンがこれを実現する 1 つの方法ですが、それが唯一の手法ではありません。他の 2 つはファクトリ クラスと名前付きパラメーターです。

また、これらの手法は相互に排他的ではないことに注意してください。目標は、アプローチの純粋さではなく、コードの読みやすさを最大化することです。

メソッドチェーン

メソッド チェーンの背後にある重要な洞察は、決して void を返すメソッドを持たないことですが、常に何かのオブジェクト、またはより多くの場合、さらなる呼び出しを可能にするインターフェイスを返すことです。

メソッドが呼び出されたのと同じオブジェクトを必ずしも返す必要はありません。つまり、常に「これを返す」必要はありません。

有用な設計手法の 1 つは、別のクラスの構成を可能にする fluent API を公開するインナー クラスを作成することです。

これには 2 つの利点があります。流暢な API を 1 か所に保持し、クラスの主要な機能から分離できることと、(内部クラスであるため) 他のクラスではできない方法でメイン クラスの内部をいじることができることです。

特定の時点で開発者が使用できるメソッドを制御するために、一連のインターフェイスを使用することができます。

ファクトリ クラス

一連の関連オブジェクトを構築したい場合があります。例としては、NHibernate Criteria API、Rhino.Mocks 期待値制約、NUnit 2.4 の新しい構文などがあります。

どちらの場合も、格納する実際のオブジェクトがありますが、それらを簡単に作成できるようにするために、必要なインスタンスを作成するための静的メソッドを提供するファクトリ クラスがあります。

たとえば、NUnit 2.4 では次のように記述できます。

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

「Is」クラスは、NUnit による評価の制約を作成するファクトリ メソッドでいっぱいの静的クラスです。

実際、浮動小数点数の丸め誤差やその他の不正確さを許容するために、テストの精度を指定できます。

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

(事前にお詫びします - 私の構文が間違っている可能性があります。)

名前付きパラメータ

それらをサポートする言語 (Smalltalk および C# 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);
于 2008-11-16T06:32:38.080 に答える
50

オブジェクト指向の .NET またはその他の言語の任意のバージョンで流暢なインターフェイスを作成できます。メソッドが常にオブジェクト自体を返すオブジェクトを作成するだけです。

たとえば、C# の場合:

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");
于 2008-11-16T02:29:24.623 に答える
16
于 2008-11-16T02:28:42.020 に答える
5

少し前に、私はあなたが今持っているのと同じ疑問を持っていました. 私はいくつかの調査を行い、現在、流暢なインターフェースを設計する技術に関する一連のブログ投稿を書いています。

でそれをチェックしてください:

C# での Fluent Interface 設計のガイドライン パート 1

Chaining X Nesting に関する興味深いセクションがあります。

次の投稿では、より深い方法でそれについて話します。

よろしくお願いします、

アンドレ・ヴィアナ

于 2010-08-05T01:30:53.320 に答える
3

流暢なインターフェイスは、オブジェクト指向プログラミングで、メソッドを含む同じインターフェイスをメソッドから常に返すことによって実現されます。したがって、バージョンに関係なく、java、javascript、およびその他のお気に入りのオブジェクト指向言語でこの効果を実現できます。

この手法は、インターフェイスを使用して達成するのが最も簡単であることがわかりました。

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

このようにして、インターフェイスを実装する具象クラスは、流暢なメソッド チェーン機能を取得します。FWIW ..上記のコードはC#1.1で書きました

この手法は、jQuery API 全体に散らばっています。

于 2008-11-16T02:27:38.120 に答える
1

これは、私がいわゆる流暢なインターフェイスまたは唯一の forary を構築した方法です。

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が必要でしたが、それは私のラムダの原因にすぎません。Brad が指摘したように、.net のどのバージョンでもこれを行うことができます。ラムダは、このようなより興味深い可能性を秘めていると思いますが。

======

他のいくつかの良い例は nHibernate の Criteria API です。nhibernate を構成するための流暢な nhibernate 拡張機能もありますが、私はそれを使用したことがありません

于 2008-11-16T02:28:05.140 に答える
1

.Net 3.5/C# 3.0 で可能なことがいくつか思い浮かびます。

  1. オブジェクトが流暢なインターフェイスを実装していない場合は、拡張メソッドを使用して呼び出しを連鎖させることができます。

  2. オブジェクトの初期化を使用して流暢にシミュレートできる場合がありますが、これはインスタンス化時にのみ機能し、単一の引数メソッド (プロパティがセッターのみである場合) でのみ機能します。これは私にはハックのように思えますが、そこにあります。

個人的には、ビルダー オブジェクトを実装している場合、関数チェーンを使用しても問題はないと思います。ビルダー オブジェクトにチェーン メソッドがある場合は、作成しているオブジェクトをクリーンに保ちます。ちょっとした考え。

于 2008-11-16T02:30:18.023 に答える
0

C# 4.0 の dynamic キーワードにより、動的なスタイル ビルダーを記述できるようになります。JSON オブジェクトの構築に関する次の記事をご覧ください。

于 2009-09-15T01:13:12.990 に答える