7

これは、Java で解決する方法がわからないことについての質問です。URI、文字列、リテラルの 3 種類のデータに基づいてトリプル ステートメントを作成したいと考えています。各タイプは別々にエンコードされています。これらの型を受け入れるエンコード メソッドを作成しました。

public static String makeStatement(URI subject, URI predicate, String object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

public static String makeStatement(String subject, URI predicate, String object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

public static String makeStatement(URI subject, URI predicate, Literal object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

private static String encode(String binding) {
    return "?" + binding;
}

private static String encode(URI uri) {
    return "<" + uri.stringValue() + ">";
}

private static String encode(Literal literal) {
    return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
}

しかし、これらのタイプの任意の組み合わせを受け入れることができるため、これには 9 つの makeStatement 関数が必要になります。これらは基本的に同じことを行っており、特に後で別のタイプを追加する可能性があるため、これは悪い考えのように思えます。

通常、私はスーパークラスを作成することを提案してそのような質問に答えますが、文字列、URI、およびリテラルを編集することはできません。別のオプションは、定義することです

public static String makeStatement(Object subject, Object predicate, Object object) {
    String encodedSubject = "", encodedPredicate = "", encodedObject = "";
    if (subject.getClass().equals(URI.class)) {
        encodedSubject = encode((URI) subject);
}
    return " " + encode(encodedSubject) + " " + encode(encodedPredicate) + " " + encode(encodedObject) + ".\n";
}

次に、各引数のクラスを確認しますが、これはあまりエレガントではないと思います。別の提案は、makeStatement(URI subjectURI、String subjectString、Literal subjectLiteral、URI predicateURI .. etc) のようなものを定義し、どの引数が null であるかを確認してそこから移動することですが、それは、私が呼び出すときに多くの null を入力することを意味します関数。3 番目のオプションはhttps://stackoverflow.com/a/12436592/1014666ですが、これも makeStatement 関数を呼び出すときにかなり余分な入力が必要になります。

助言がありますか?

4

5 に答える 5

3

ビルダー パターンを使用できます。

    public class StatementMaker {
    private static String encode(String binding) {
        return "?" + binding;
    }

    private static String encode(URI uri) {
        return "<" + uri.stringValue() + ">";
    }

    private static String encode(Literal literal) {
        return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
    }

    public static Statement from(String b) {
        return new Statement(encode(b));
    }

    public static Statement from(URI b) {
        return new Statement(encode(b));
    }

    public static Statement from(Literal b) {
        return new Statement(encode(b));
    }

    public static class Statement {

        private StringBuilder buf;
        private Statement(String s) {
            buf = new StringBuilder(" ");
            buf.append(s);
        }

        public Statement with(String s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public Statement with(URI s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public Statement with(Literal s) {
            buf.append(" ").append(encode(b));
            return this;
        }

        public String toString() {
            return buf.toString() + ".\n";
        }

    }
}

ステートメントを次のように作成できるようになりました。

StatementMaker.from(subject).with(predicate).with(object).toString()

ステートメントが必要なコードでは、静的インポートを使用してコードをさらに短縮できます。

import static my.package.StatementMaker.from;

次に、ステートメントは次のように縮小されます。

from(subject).with(predicate).with(object).toString()

内部クラスにさらに 3 つのメソッドを追加できます。

public static class Statement {

    private StringBuilder buf;
    private Statement(String s) {
        buf = new StringBuilder(" ");
        buf.append(s);
    }

    public Statement with(String s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public Statement with(URI s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public Statement with(Literal s) {
        buf.append(" ").append(encode(b));
        return this;
    }

    public String and(String s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }

    public String and(URI s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }

    public String and(Literal s) {
        buf.append(" ").append(encode(b));
        return buf.toString() + ".\n";
    }


    public String toString() {
        return buf.toString() + ".\n";
    }

}

toString()次に、次のような呼び出しを回避できます。

String statement = from(subject).with(predicate).and(object);

于 2013-10-11T09:45:14.783 に答える
2

いくつかのオプションしかない場合、メソッドのオーバーロードはうまく機能します。あなたがここに持っているのは、少し強迫観念です。簡単に変換できる方法があれば、すべてのオプションを用意する必要はありません。

したがって、考えられるすべての選択肢を持つことを忘れて、最もよく使用されるものを利用できるようにします。

于 2013-10-11T08:40:24.630 に答える
1
public static String makeStatement(Object subject, Object predicate, Object object) {
    return " " + encode(subject) + " " + encode(predicate) + " " + encode(object) + ".\n";
}

private static String encode(Object obj) {
   String  encodedOj ="";
   if (obj.getClass().equals(URI.class)) {
        encodedOj = encode((URI) obj);
   }else if(obj.getClass().equals(Literal.class)){
      encodedOj = encode((Literal) obj);
   }else if(obj.getClass().equals(String.class)){
      encodedOj = encode((String) obj);
   } 
   return encodedOj;
}

private static String encode(String binding) {
    return "?" + binding;
}

private static String encode(URI uri) {
    return "<" + uri.stringValue() + ">";
}

private static String encode(Literal literal) {
    return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
}
于 2013-10-11T10:32:07.483 に答える
0

静的ファクトリ メソッド ( Effective Java、項目 1を参照) と匿名クラス (クロージャーのようなものとして機能)を使用して、楽しくて使いやすいラッパーを作成できます。

方法は次のとおりです。

public class Item {

    private static interface Methods {
        public String encode();
    }

    private final Methods methods;

    private Item(Methods methods) {
        this.methods = methods;
    }

    public static Item of(final String binding) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "?" + binding;
            }
        });
    }

    public static Item of(final URI uri) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "<" + uri.stringValue() + ">";
            }
        });
    }

    public static Item of(final Literal literal) {
        return new Item(new Methods() {
            @Override
            public String encode() {
                return "\"" + literal.stringValue() + "\"" + literal.getDatatype();
            }
        });
    }

    public String encode() {
        return methods.encode();
    }
}

このアプローチを使用して、サポートされている新しい型 (要件の 1 つでした) を追加するのは非常に簡単です。この型を受け入れる新しい静的ファクトリ メソッドを作成するだけですItem.of(NewType val)

したがって、次の方法があります。

public static String makeStatement(Item subject, Item predicate, Item object) {
    return subject.encode() + " " + predicate.encode() + " " + object.encode();
}

そして、次のように呼び出します。

makeStatement(Item.of(subject), Item.of(predicate), Item.of(object));

新しいメソッドの追加も非常に簡単です (ただし、拡張ではなく変更のようなものです)。それらをMethodsインターフェースに追加し、サポートされているすべての型のクロージャーに実装するだけです。とにかく、コンパイラはあなたにそれをさせます。

于 2013-10-11T11:43:45.673 に答える