Я думаю, что смогу дать вам лучший ответ после просмотра ваших правок - ваш лучший выбор, вероятно, является заводским паттерном. (Не мило, но лучше, чем синглтон).
abstract class Widget
public static Widget[] getAllWidgetsOfType(Class widgetType) {
if(widgetType instanceof ...)
}
class Ball extends Widget
class Stick extends Widget
class Toy extends Widget
Это не очень хороший способ сделать это, но это типично. Hibernate - это инструмент, который вы обычно используете для решения этой проблемы, именно для этого он и предназначен.
Большая проблема заключается в том, что он требует редактирования базового класса всякий раз, когда вы добавляете новый класс заданного типа. Этого нельзя обойти без отражения. Если вы хотите использовать отражение, вы можете реализовать его следующим образом (Psuedocode, я не собираюсь искать точный синтаксис для отражения, но он не намного сложнее, чем этот):
public static Widget[] getAllWidgetsOfType(Class widgetType) {
Method staticMethod=widgetType.getStaticMethod("getAllInstances");
return staticMethod.invoke();
}
Это дало бы решение, о котором вы просили (быть обеспокоенным необходимостью изменять базовый класс каждый раз, когда вы добавляете дочерний класс, - это хороший инстинкт).
Вы также можете сделать его методом экземпляра вместо статического. В этом нет необходимости, но вы можете создать прототип метода (аннотация) в Widget.
Опять же, все это излишне и небрежно по сравнению с Hibernate ...
Редактировать: Если вы передали живой экземпляр «Пустого» шара, клюшки или игрушки вместо его объекта «Класс», вы можете просто вызвать унаследованный метод и вообще не использовать отражение. Это также будет работать, но вы должны расширить определение виджета, включив в него в качестве ключа «пустой» экземпляр.