URLを解析してデータを抽出するライブラリがあります。 URLごとに1つのクラスがあります。どのクラスがユーザーから提供されたURLを処理するかを知るために、私は以下のコードを持っています。工場で正しい実装を動的に呼び出す
public class HostExtractorFactory {
private HostExtractorFactory() {
}
public static HostExtractor getHostExtractor(URL url)
throws URLNotSupportedException {
String host = url.getHost();
switch (host) {
case HostExtractorABC.HOST_NAME:
return HostExtractorAbc.getInstance();
case HostExtractorDEF.HOST_NAME:
return HostExtractorDef.getInstance();
case HostExtractorGHI.HOST_NAME:
return HostExtractorGhi.getInstance();
default:
throw new URLNotSupportedException(
"The url provided does not have a corresponding HostExtractor: ["
+ host + "]");
}
}
}
問題は、ユーザーが自分のswitch文が成長していることを意味する、解析されるように多くのURLを要求しているです。誰かがパーサを使いこなすたびに、コードを修正する必要があります。
これを終了するには、マップを作成して公開することに決めました。そのクラスが作成されると、ホスト名と抽出者を工場に登録することで自分自身を工場に登録できます。以下は、このアイデアを実装した工場です。
public class HostExtractorFactory {
private static final Map<String, HostExtractor> EXTRACTOR_MAPPING = new HashMap<>();
private HostExtractorFactory() {
}
public static HostExtractor getHostExtractor(URL url)
throws URLNotSupportedException {
String host = url.getHost();
if(EXTRACTOR_MAPPING.containsKey(host)) {
return EXTRACTOR_MAPPING.get(host);
} else {
throw new URLNotSupportedException(
"The url provided does not have a corresponding HostExtractor: ["
+ host + "]");
}
}
public static void register(String hostname, HostExtractor extractor) {
if(StringUtils.isBlank(hostname) == false && extractor != null) {
EXTRACTOR_MAPPING.put(hostname, extractor);
}
}
}
、ユーザーがそのようにそれを使用します。ユーザークラスを:
public class HostExtractorABC extends HostExtractor {
public final static String HOST_NAME = "www.abc.com";
private static class HostPageExtractorLoader {
private static final HostExtractorABC INSTANCE = new HostExtractorABC();
}
private HostExtractorABC() {
if (HostPageExtractorLoader.INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
HostExtractorFactory.register(HOST_NAME, this);
}
public static HostExtractorABC getInstance() {
return HostPageExtractorLoader.INSTANCE;
}
...
}
私はこれが機能することはありません気づいたとき、私は自分の背中を撫でました。 URLを受け取ったときにロードされず、コンストラクタが実行されないことを意味するファクトリだけがロードされ、マップは常に空です。だから私はドローイングボードに戻っていますが、これを動作させるためのアイデアや、この厄介なswitch文を取り除くための別のアプローチが欲しいと思います。
S
** reflection **を使用することができます。または、既知の、または「利用したい」クラスをすべてリストする必要があります。設定ファイルなど... 'org.reflections'は、クラスパスをスキャンするための素敵な軽量なlibです。 – dedek
クラス名をシンプルなテキストファイルに列挙してください。シンプルなテキストファイルでは、それらを維持したり、ファクトリの構築を静的コンストラクタに移したり、すべてのエントリに対して 'Class.forname'(https://stackoverflow.com/q/8100376/13075)を使用しますファクトリの初期化メソッドでファイルの – Henrik
または、クラスに適用する注釈を導入し、工場出荷時のクラスパスをスキャンします。 – Henrik