私はシングルトンの特定のクラス階層を継承しましたが、その宣言は以下に要約されています (実装は他にもあります。問題を示すために最小限のセットを示しているだけです)。instance
何よりも、シングルトンが継承されていることと、基本クラスの方法がサブクラスの静的初期化子でその値を上書きしているため、私には最高の匂いがします。
すべての実装がfoo.common
親パッケージにある場合、instance
メンバーとgetInstance()
メソッドをそれらから削除し、クラスとそのコンストラクターをパッケージローカルにし、いくつかのパブリック ファクトリ クラスにfoo.common
それぞれの単一のインスタンスを作成させ、その単一のインスタンスを保持することを検討します。それぞれを内部的に (IReadOnly
またはの実装であるかどうかによって分割IReadWrite
)、いくつかの列挙型に基づいて要求された実装をインターフェイス型として返すパブリック ルックアップ メソッドをいくつか提供します。
ただし、多くのアプリに共通するものを対象としているため、実装は外部にある可能性がありfoo.common
、foo.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
}