1

私はシングルトンの特定のクラス階層を継承しましたが、その宣言は以下に要約されています (実装は他にもあります。問題を示すために最小限のセットを示しているだけです)。instance何よりも、シングルトンが継承されていることと、基本クラスの方法がサブクラスの静的初期化子でその値を上書きしているため、私には最高の匂いがします。

すべての実装がfoo.common親パッケージにある場合、instanceメンバーとgetInstance()メソッドをそれらから削除し、クラスとそのコンストラクターをパッケージローカルにし、いくつかのパブリック ファクトリ クラスにfoo.commonそれぞれの単一のインスタンスを作成させ、その単一のインスタンスを保持することを検討します。それぞれを内部的に (IReadOnlyまたはの実装であるかどうかによって分割IReadWrite)、いくつかの列挙型に基づいて要求された実装をインターフェイス型として返すパブリック ルックアップ メソッドをいくつか提供します。

ただし、多くのアプリに共通するものを対象としているため、実装は外部にある可能性がありfoo.commonfoo.commonそのような「より具体的な」パッケージに依存することは許可されていません。foo.commonだから、そんな単純なことはできない。じゃあ何?

最初のインターフェース:

package foo.common.config;
public interface IReadOnly
{
    void load();
    String getVal(String key);
}

2 番目のインターフェイス:

package foo.common.config;
public interface IReadWrite extends IReadOnly
{
    void save();
    void setVal(String key, String value);
}

最初の実装:

package foo.common.config;
public class ReadOnlyImpl implements IReadOnly
{
    protected static IReadOnly instance;

    static {
        instance = new ReadOnlyImpl();
    }

    public static IReadOnly getInstance() {
        return instance;
    }

    protected ReadOnlyImpl() {}

    // implement methods in IReadOnly
}

2 回目の実装

package foo.common.config;
public class ReadWriteImpl extends ReadOnlyImpl implements IReadWrite
{
    static {
        instance = new ReadWriteImpl();
    }

    public static IReadWrite getInstance() {
        return (IReadWrite) instance;
    }

    protected ReadWriteImpl() {
        super();
    }

    // Implement methods in IReadWrite
}

3 番目の実装:

// While things in this package can depend
// on things in foo.common, nothing in 
// foo.common is allowed to depend on this package.
package foo.apps.someapp;
public class MoreSpecificReadWriteImpl extends ReadWriteImpl
{
    static {
        instance = new MoreSpecificReadWriteImpl();
    }

    public static IReadWrite getInstance() {
        return (IReadWrite) instance;
    }

    protected MoreSpecificReadWrite() {
        super();
    }

    // Override superclass methods to do something specific
}
4

1 に答える 1

1

パッケージfoo.apps.someappを脇に置いて、パッケージfoo.common.configの設計が間違っています。

IReadOnly o1=ReadOnlyImpl.getInstance(); // ok, returns ReadOnlyImpl
...
ReadWrite o2=ReadWriteImpl.getInstance(); // ok, returns ReadWriteImpl 
...
IReadOnly o3=ReadOnlyImpl.getInstance(); // bad, returns ReadWriteImpl, the same as o2.

その理由は、すべてのクラスが同じ静的変数ReadOnlyImpl.instanceを使用するためです。MoreSpecificReadWriteImplを含むすべてのクラスで個別の変数を使用します。これが合わない場合は、Springコンテナまたは同様のフレームワークの使用を検討してください。

于 2012-05-04T05:02:25.297 に答える