2

URI の作成を容易にする小さな Web API を作成します。各リソース クラスには、必要なパラメーターを受け取るメソッドが含まれてcreateURIいる必要があります。このメソッドは、ヘルパー メソッド をpopulateUriTemplateバックグラウンドで使用して URI 文字列を作成する必要があります。populateUriTemplateURI テンプレートを設定するには、キーと値のペアが必要です。Scala や Python などの別の言語では、名前付きパラメーターを使用しますが、Java はそれらをサポートしていません。問題は、Java で名前付きパラメーターをシミュレートする方法です。

簡単な解決策は、マップを作成することです。

public String createUri(int id, String name){
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("id", id);
    params.put("name", name);
    return populateUriTemplate(params);
}

しかし、最初にマップを作成して各パラメーターを配置するのは好きではありません。

もう 1 つのアイデアは、静的メソッド を使用paramしてキーと値のペアを作成することです。

public String createUri(int id, String name){
    return populateUriTemplate(param("id", id), param("name", name));
}

私にはずっと良く見えます!

さらにいくつかの文字が必要な場合でも、より自明にするために少し洗練することができます。

public String createUri(int id, String name){
    return populateUriTemplate(key("id").value(id), key("name").value(name));
}

ビルダー パターンも考えましたが、これでは API のユーザーがリソース クラスごとに明示的なビルダーを作成する必要があり、面倒でメリットがありません。toString適切に実装されたメソッドが存在する限り、パラメーターの型は重要ではありません。

私のお気に入りは、上記の静的メソッド (param(key, value)またはkey(k).value(v)) を使用した両方のアプローチの 1 つです。この場合、名前付きパラメーターをシミュレートするより良い方法を知っていますか?

4

6 に答える 6

2

ビルダー パターンのアイデアについては、 Stephan Schmidt によるこのブログ投稿を参照してください。

Callableまた、流暢なインターフェイス、 、および静的メソッドを使用して、次のことを行うというアイデアも与えてくれました。

createUri().id(5).name("dennetik").call();

これには、静的メソッドを使用してCallableクラス ( ) を作成する必要があります。CreateUri

public static final CreateUriFluentInterface createUri() {
    return FluentInterface.of(new CreateUri(), CreateUriFluentInterface.class);
}

そして、このような流暢なインターフェース:

public interface CreateUriFluentInterface {
    public CreateUriFluentInterface id(Integer id);
    public CreateUriFluentInterface name(String name);
}

定型コードではないのはどれですか?

(まあ、その恐ろしい名前CreateUriFluentInterfaceを少しトーンダウンすると、そうではありません。)

(通話を に再ルーティングできるようにするには、おそらく をCreateUriFluentInterface拡張する必要があります)Callable<String>Callable#call()

于 2010-06-20T11:33:53.407 に答える
1
populateUriTemplate("id",id, "name",name);

void populateUriTemplate(Object... nvs){
    for(int i=0; i<nvs.length/2; i++)
        ....
}
于 2010-06-20T15:48:14.803 に答える
0

多分あなたはこのアプローチが好きです:

class Params {
    private HashMap<String, Object> allParams = new HashMap<String,Object>();

    public Params(ParamEntry...params) {
        for( ParamEntry p : params ) {
            allParams.put(p.name, p.value);
        }
    }

    public getParam(String name) {
           return allParams.get(name);
    }

    class ParamEntry {
        public String name;
        public Object value;
    }
}

public String createUri(Params.ParamsEntry ... params){
    return populateUriTemplate(new Params(params));
}

それを呼び出すには

createUri(new Param.ParamEntry("name", valueObject) );

populateUriTemplate 内...ちょうどuse params.get("name");

于 2010-06-20T11:09:23.597 に答える
0

Spring MVCはまさにこれを行います。コントローラ クラスの特定のメソッドにリクエストをバインドできるだけでなく、リクエスト パラメータをメソッド パラメータにバインドすることもできます。それがどのように機能するかを見てみることができますが、基本的には、正しいリクエスト パラメータを正しいメソッド パラメータにマッピングする戦略を選択します。

基本的に次のようなものを取得します。

public String createUri(@RequestParam int id, @RequestParam String name){
    return populateUriTemplate(id, name);
}
于 2010-06-20T11:10:11.460 に答える
0

これはほとんどばかげており、少し話題から外れていますが、Lombok の@Builderアノテーションを使用すると、これを目的の結果に近づけることができます。

さらに、ビルダー、ビルダー メソッド、およびビルド メソッドの名前を次のように変更すると_、それらはほとんどなくなります。

import static foo.Template._;

class Resource {
    String createURI(String id, String name) {
        return populateURITemplate(_.id(id).name(name)._());
    }
    String populateURITemplate(Template t ){
        return t.id+"="+t.name;
    }
}
@Builder(builderClassName = "_", builderMethodName = "_", buildMethodName = "_" )
class Template {
    static _ _ = _();
    String id;
    String name;
}
于 2015-09-30T21:05:54.277 に答える
0

名前付きパラメータはそうではありません:

この場合、名前付きパラメーターを使用してもコードがすっきりしません。型の安全性が失われ、存在しない識別子に関するコンパイラの警告が失われるため、Java では物事がより複雑になり、エラーが発生しやすくなると私は主張します。

TypeSafe 不変流暢ビルダー:

UrlBuilder私は今年初めに実装に関する記事を書きました。それは、必須入力の構築順序を強制し、適切なデフォルトを持つオプション部分も可能にする、型安全で流暢なインターフェースを示しています。

ここで、私が使用するアプローチがかなり冗長であることを最初に認めますが、最初の代償を払えば、非常に生産的です。依存性注入で動作し、簡単に単体テストが可能で、最も重要なことは、特殊化のために構成可能です。

    final URL url1 = new UrlBuilder().scheme("http").host("www.google.com").build();
    System.out.println("url1 = " + url1);
    final URL url2 = new UrlBuilder().scheme("https").userInfo("xkcd", "correcthorsebatterystaple").host("admin.xkcd.com").build();
    System.out.println("url2 = " + url2);

プロデュース:

url1 = http://www.google.com
url2 = https://xkcd:correcthorsebatterystaple@admin.xkcd.com

私は、実験中の別のアプローチを使用して、インターフェイスの匿名内部クラスの実装の冗長性に対処しています。動的プロキシを使用したインターフェイスからの値オブジェクトのタイプ セーフな実装

これにより、ボイラープレート値オブジェクトがなくなり、それらが置き換えられますMap<String,?>が、動的に生成されたタイプ セーフで不変のInterfaceラッパーが配置されます。

これらの両方について読んで、それらを組み合わせることで、名前付きプロパティよりも優れたソリューションが得られることを確認することをお勧めします。

動的プロキシを使用してリファクタリングする時間ができたら、UrlBuilderそれに関する別のブログ投稿も投稿します。

Guice による名前付きパラメーター

名前付きパラメーターに固執している場合は、Guice @Named bindingsを確認することをお勧めします。コンパイルの型チェックと安全性は引き続き失われますが、少なくとも Guice からいくつかの検証が得られます。

public class RealBillingService は BillingService を実装します {

@Inject
public RealBillingService(@Named("Checkout") CreditCardProcessor processor,
    TransactionLog transactionLog) {
...
}
于 2015-09-30T21:25:21.603 に答える