私はインタビューの中で、この質問をしました。
そこ3クラスはA
、B extends A
&C extends B
。当社は、これらの制約に準拠し、これらのクラスを設計する必要があります
- クライアントがの唯一のインスタンスをインスタンス化することができ
A
、1つのインスタンスB
&1つのインスタンスC
で自分のデフォルトコンストラクタを使用してnew
キーワードを。 - これらのクラスのいずれかの別のインスタンスを作成しようとすると、例外が発生します。
- クラスの設計者は、そのクライアントが暗黙的に上記の規則を経験するので(すなわち、それはルール上記に準拠するように、クライアントの責任ではありません)、2つの規則上強制しなければなりません。
私が使用してのアプローチを示唆しましたstatic Map<Class, Object>
。だから、例えばのために誰かが呼び出されたときにnew B()
、それがあればチェックしますmap.contains(B.class)
。yesの場合は、例外をスロー&そうでない場合は、インスタンス保存地図に&オブジェクトを作成することができます。
しかし、次の質問だった私は、各クラスでこのアプローチを強制するだろうか?私のアプローチごとのように、各コンストラクタは慎重マップを移入する必要がありますそれ以外の場合は、制約が解除されます。
どのように私はこの問題を解決するのでしょうか?
しかし、次の質問は、私は各クラスにこのアプローチを適用するだろうかでしたか?私のアプローチごとのように、各コンストラクタは慎重マップを移入する必要がありますそれ以外の場合は、制約が解除されます。
単にいくつかの明確なユーティリティクラスにそのマップ、およびその周りのコードを置くこともできます。だから、それぞれ自分のクラスでは、のような何かができること:
public WhateverClassConstructor() {
synchroized(someLock) {
SingeltonChecker.ensureUnique(this);
とともに
public static void ensureUnique(Object objectToAdd) {
Class<?> classToAdd = o.getClass();
...
そして、CはBがAを拡張して拡張しているという事実を考えると、あなたはおそらく唯一一方、クラスAのコンストラクタで呼び出しは、へのあなたの最初の呼び出しがあることを想像することを必要とするnew C()
C-コンストラクタで例外が発生しますが、2番目の呼び出しではないだろう。確かに、それ自体に問題があるが、それでも、疑問が残るが:完全かつ正確なマップに追加する前に、どのようにオブジェクトを確保しますが初期化されました!
このように:そこにあるトンなどのユーティリティコードを記述する際に考慮すべき事柄のは。したがって、私の答えは、与えられた設計点の実用的でない、ほとんど愚かネスに焦点を当て、と簡単な例として何かのために、それを捨てると他のソリューションのために行くことをお勧め:
public enum SingletonObjectHolder {
private final Object hold;
A_INSTANCE(new A()), B_INSTANCE(new B())...
public Object getSingleton() { return hold; }
private SingletonObjectHolder(Object o) { hold = o };
とき、人々に技術的な答えを与えるためにしようとあまりにも多くの時間を無駄にしてはいけない本当のポイントがすることですない足に自分自身を撮影。そして間違い作るん:堅牢で正確な作業にマップベースの「シングルトン」のアプローチを取得し、コンテキストのすべての種類のために、それを考慮して、本当に難しいです。
言い換えれば、私はあなたのインタビューの中で、この質問をするならば、私は答えを聞きたいだろうに挑戦その恐ろしい設計点を。確かに、特定のシナリオのためのソリューションを概説し、あなたの時間の10%を費やしました。しかし、それはとても悪いです理由を説明する時間の90%を費やし、そしてなぜ他のソリューションは非常に良いだろう。