Но следующий вопрос состоял в том, как бы я применял этот подход в каждом классе? Согласно моему подходу каждый конструктор должен был бы тщательно заполнить карту, иначе это нарушит ограничение.
Просто поместив эту карту и код вокруг нее в какой-то отдельный класс Utility. Чтобы каждый из ваших классов мог делать что-то вроде:
public WhateverClassConstructor() {
synchroized(someLock) {
SingeltonChecker.ensureUnique(this);
с
public static void ensureUnique(Object objectToAdd) {
Class<?> classToAdd = o.getClass();
...
А учитывая тот факт, что C расширяет B, расширяет A, вам, вероятно, нужен только этот вызов в конструкторе класса A. С другой стороны, представьте, что ваш первый вызов new C()
вызывает исключение в C-конструкторе, но второй звонок не будет. Конечно, это проблема сама по себе, но все же остается вопрос: как вы гарантируете, что объект был полностью и правильно инициализирован перед добавлением его в такую карту?!
Таким образом: при написании такого служебного кода необходимо учитывать тонну . Таким образом, мой ответ будет сосредоточен на непрактичной, почти глупой заданной точке проектирования, и предложит отбросить его и перейти к другим решениям, например, к такому простому как:
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 };
Не тратьте слишком много времени, пытаясь дать людям технический ответ, когда real указывает на , а не , стреляйте себе в ногу. И не заблуждайтесь: заставить этот основанный на карте подход «синглтон» работать надежно и корректно для всех видов контекста, считайте, что действительно трудно .
Другими словами: если бы я задал вам этот вопрос в интервью, я бы хотел услышать ответ, который оспаривает эту ужасную идею. Конечно, вы потратили 10% своего времени на обдумывание решения для данного сценария. Но потратьте 90% времени, объясняя, почему это так плохо, и почему другие решения будут намного лучше.