Как я могу создать семью синглетонов? - PullRequest
1 голос
/ 03 мая 2010

Я хочу создать набор классов, которые имеют много общего поведения. Конечно, в ООП, когда вы думаете, что автоматически думаете «абстрактный класс с подклассами». Но я хочу, чтобы эти классы имели статический список экземпляров класса. Список должен функционировать как своего рода одиночка в классе. Я имею в виду, что у каждого из подклассов есть синглтон, а не у одного. «Синглтон» для этого подкласса, а не настоящий синглтон. Но если он статический, как я могу его унаследовать?

Конечно, такой код не будет работать:

public abstract A
{
  static List<A> myList;
  public static List getList()
  {
    if (myList==null)
      myList=new ArrayList<A>(10);
    return myList;
  }
  public static A getSomethingFromList()
  {
    List listInstance=getList();
    ... do stuff with list ...
  }
  public int getSomethingFromA()
  {
    ... regular code acting against current instance ...
  }
}
public class A1 extends A
{
  ...
}
public class A2 extends A
{
   ...
}

A1 somethingfromA1List=(A1) A1.getSomethingFromList();
A2 somethingfromA2List=(A2) A2.getSomethingFromList();

Содержимое списка для каждого подкласса будет различным, но весь код для работы со списками будет одинаковым.

Проблема с приведенным выше кодом состоит в том, что у меня будет только один список для всех подклассов, и я хочу один для каждого. Да, я мог бы реплицировать код для объявления статического списка в каждом из подклассов, но тогда мне также пришлось бы реплицировать весь код, который добавляется в списки, и выполняет поиск в списке и т. Д., Что скорее противоречит цели подкласса.

Есть идеи, как это сделать без репликации кода?

Обновление

Чтобы прояснить ситуацию с BlueRaja и, возможно, с другими, позвольте мне немного подробнее рассказать о том, что я пытаюсь сделать.

У меня есть несколько статусов и кодов, которые требуют аналогичного поведения. Они похожи на перечисления в том, что я хочу, чтобы для каждого возможного состояния кода были безопасные для типов экземпляры, но они входят в несколько наборов, поэтому я не могу просто сделать одно перечисление для них всех.

Так, например, у меня есть статус заказа, который имеет значения для заказа, отгружено, получено и некоторые специальные значения. У меня есть тип элемента со значениями для товаров и услуг. У меня есть запас по сравнению с обычаем. И т.д.

Если бы это было все, что было, я просто сделал бы перечисление для каждого. Но мне нужно другое поведение, например, возможность искать объект по текстовому значению, например, когда мы читаем это из базы данных; построение выпадающего списка со всеми вариантами текстового описания; и т.д. Насколько я знаю, я не могу сделать это с помощью enum, потому что у меня есть несколько наборов кодов, каждый из которых имеет общее поведение, которое я хочу наследовать, и я не могу создать подкласс enum. Помещение всех кодов в одно перечисление лишит безопасность типов для одного кода по сравнению с другим, а также не обеспечит готовый способ сбора списка значений для определенного типа кода.

Ответы [ 6 ]

5 голосов
/ 03 мая 2010

Вы можете использовать static Map<Class, YourClass> = new ConcurrentHashMap<..>() в родительском классе и использовать эту карту для добавления / извлечения экземпляров.

Хотя такая большая зависимость от синглетонов звучит для меня как плохой дизайн - вы должны попытаться избежать этого.

1 голос
/ 03 мая 2010

Что плохого в синглетах?

Изменить: после ответа на вопрос: Вы говорите: «Я хочу создать набор классов, которые имеют много общего поведения» - это, для меня, не предполагает «абстрактный класс с подклассами вообще», поскольку абстрактный класс не имеет поведения. Он предлагает отдельный объект, реализующий общее поведение, и множество классов, объединяющих этот отдельный объект.

0 голосов
/ 03 мая 2010

Если вам нужна одноэлементная функциональность и в то же время вы хотите получить выгоду от наследования, вам следует рассмотреть такие структуры Dependency Injection, как Spring или PicoContainer . Даже если ваше приложение довольно маленькое, ваша жизнь все равно будет проще с каркасом, управляющим зависимостями.

0 голосов
/ 03 мая 2010

Вы можете использовать индексы класса, статический список не нужен, вы можете просто использовать индексы, которые ссылаются на набор этих классов и подкласса. Вот пример: http://www.java2s.com/Code/CSharp/Class-Interface/Indexerallowarraylikeindex.htm

0 голосов
/ 03 мая 2010

Я бы подумал о фабричном методе:

public class Factory {
  private static final A1 a1Instance = new A1(
          Collections.synchronizedList(new ArrayList<something>(100)));
  private static final A2 a2Instance = new A2(
          Collections.synchronizedList(new ArrayList<something>(100)));

  public static A getA1() { return a1Instance; }
  public static A getA2() { return a2Instance; }
}

Вашему А, конечно, больше не понадобятся все эти static методы.

0 голосов
/ 03 мая 2010

Судя по звукам, вам действительно нужен класс enum с пользовательскими свойствами и поведения . См. здесь для примера предельной мощности перечислений в Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...