6

例を挙げて質問をよりよく説明します。データへのアクセスに使用できるインターフェイス モデルがあります。XMl 、 txt 形式など、さまざまな形式でデータを表すことができるモデルのさまざまな実装が存在する可能性があります。モデルは形式には関係ありません。そのような実装の 1 つがmyxmlModelだとしましょう。

ここで、 myxmlModelとModelの他のすべての実装をシングルトン パターンに従うように強制したいと考えています。通常の方法は、myxmlModelsコンストラクターをプライベートにし、myModel クラスのインスタンスを返す静的ファクトリ メソッドを提供することです。しかし、問題は、インターフェイスが静的メソッド定義を持つことができないことです。その結果、 Modelのすべての実装で特定の Factory メソッド定義を強制することはできません。したがって、ある実装はgetObject()を提供することで終了し、別の実装は get NewModel() を提供する場合があります。.

回避策の 1 つは、 myxmlModel のコンストラクターへのパッケージ アクセスを許可し、 myxmlModelオブジェクトを作成して後で使用するためにキャッシュする Factory クラスを作成することです。

同じ機能を達成するためのより良い方法があるかどうか疑問に思っていました。

4

5 に答える 5

4
  1. インターフェイス Model のインスタンスを返すファクトリを作成します。
  2. モデルのパッケージ プライベート クラスのすべての具体的な実装を、ファクトリと同じパッケージに作成します。
  3. モデルがシングルトンであり、Java 5 以降を使用している場合は、より安全であるため、従来のシングルトンの代わりに enum を使用してください。
public enum MyXMLModel{  
INSTANCE();  
//rest of class  
};

編集: 別の可能性は、すべての作業を行うデリゲート クラスを作成し、列挙型を使用してすべてのモデル オプションを提供することです。

例えば:

class MyXMLModelDelegate implements Model {
public void foo() { /*does foo*/}
...
}

class MyJSONModelDelegate implements Model {
public void foo() { /*does foo*/ }
...
}

public enum Models {
XML(new MyXMLModelDelgate()),
JSON(new MyJSONModelDelegate());

private Model delegate;
public Models(Model delegate) { this.delegate=delegate; }

public void foo() { delegate.foo(); }
}
于 2009-07-30T12:36:20.250 に答える
2

リフレクションを使用できます。このようなもの:

public interface Model {
  class Singleton {
    public static Model instance(Class<? extends Model> modelClass) {
      try {
        return (Model)modelClass.getField("instance").get(null);
     } catch (blah-blah) {
       blah-blah
     }
  }
}

public class XmlModel implements Model {
  private static final Model instance = new XmlModel();

  private XmlModel() {
  }
}

利用方法:

Model.Singleton.instance(XmlModel.class)

実際、私はこのコードがあまり好きではありません:)。まず、リフレクションを使用します-非常に遅い、次に-クラスの定義が間違っている場合、ランタイムエラーが発生する可能性があります。

于 2009-07-30T15:10:21.020 に答える
0

インターフェイスを抽象クラスにリファクタリングできますか? これにより、特定のファクトリ メソッドをすべての実装クラスに強制的に適用できます。

于 2009-07-30T12:33:23.697 に答える
0

私は自分自身に同じ質問をしていました。そして、私は同じ答えを提案しました;-)

現在、私は通常、「強制」動作をやめ、ドキュメントに依存しています。シングルトンの側面が非常に説得力があり、どうしても強制する必要があるケースは見つかりませんでした。これは、プロジェクトの「ベスト プラクティス」にすぎません。

私は通常、Spring を使用してそのようなオブジェクトをインスタンス化します。それをシングルトンにするのは Spring 構成です。安全でとても簡単... ​​さらに Spring の利点 (プロキシ、別のオブジェクトを一度置換していくつかのテストを行うなど...)

于 2009-07-30T12:39:19.577 に答える
0

これは、kts の回答に対するコメント/説明に対する回答です。本当の問題は、Singleton パターンを使用するのではなく、代わりに Eclipse (Equinox) 拡張ポイント スキーマを定義して、Singleton に貢献できるようにすることでしょうか?

IConfigurationElement.createExecutableExtension を呼び出すたびに新しいインスタンスを作成するため、これは実行できないと思います。これは、シングルトンの要件とはまったく互換性がありません。したがって、誰もがインスタンスを作成できるように、パブリックのデフォルト コンストラクターが必要です。

プラグインがモデルではなく ModelFactory を提供するように拡張ポイントの定義を変更できない限り、

public interface ModelFactory {

  public Model getModelInstance();

}

したがって、拡張機能のユーザーは ModelFactory をインスタンス化し、それを使用してシングルトンを取得します。

私が間違っていると推測した場合は、コメントを残してください。回答を削除します;)

于 2009-07-30T13:27:30.867 に答える