views:

132

answers:

6

I want to create a set of classes that share a lot of common behavior. Of course in OOP when you think that you automatically think "abstract class with subclasses". But among the things I want these classes to do is to each have a static list of instances of the class. The list should function as sort of a singleton within the class. I mean each of the sub-classes has a singleton, not that they share one. "Singleton" to that subclass, not a true singleton. But if it's a static, how can I inherit it?

Of course code like this won't work:

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();

The contents of the list for each subclass would be different, but all the code to work on the lists would be the same.

The problem with the above code is that I'd only have one list for all the subclasses, and I want one for each. Yes, I could replicate the code to declare the static list in each of the subclasses, but then I'd also have to replicate all the code that adds to the lists and searches the list, etc, which rather defeats the purpose of subclassing.

Any ideas on how to do this without replicating code?

Update

To clarify for BlueRaja and perhaps others, let me be a little more specific about what I'm trying to do.

I have a number of statuses and codes that require similar behavior. They are like enums in that I want type-safe instances for each possible code state, but they come in multiple sets so I cannot just make one enum for them all.

So for example I have order status, that has values for on-order, shipped, received, and some special values. I have item type, with values for merchandise versus service. I have stock versus custom. Etc.

If that was all there was to it I'd just make an enum for each. But there's other behavior I need, like ability to look up an object by a text value, e.g. when we read it from the database; building a drop down listing all the choices by a text description; etc. To the best of my knowledge, I can't do this with an enum because I have several sets of codes each with common behavior that I want to inherit, and I can't subclass an enum. Putting all the codes in a single enum would abandon type safety on one code versus another, as well as proving no ready way to collect the list of values for a particular code type.

+4  A: 

You can use a static Map<Class, YourClass> = new ConcurrentHashMap<..>() in the parent class and use that map to add/retrieve the instances.

Though such large reliance on singletons sounds to me like a bad design - you should try to avoid it.

Bozho
The catch to this is: How can a static in the subclass pull the appropriate entry from the HashMap? The only way I see to do this is to leave the static in the superclass and pass the class name as a parameter, like "A1 a1=(A1) A.getSomethingFromA(A1.class)". Do-able, but a little awkward. Do you have an easier way in mind?
Jay
+1  A: 

What is so bad about singletons?

Edit: After a question response: You say "I want to create a set of classes that share a lot of common behaviour" - that, to me, does not suggest "abstract class with subclasses at all", as an abstract class has no behaviour. It suggests a separate object implementing the common behaviour, and a lot of classes aggregating that separate object.

MadKeithV
Okay. So how would you solve the problem without a singleton?
Jay
You say "I want to create a set of classes that share a lot of common behaviour" - that, to me, does *not* suggest "abstract class with subclasses at all", as an abstract class has no behaviour. It suggests a separate object implementing the common behaviour, and a lot of classes aggregating that separate object.
MadKeithV
A: 

From the sounds of it, what you really want is an enum class with custom properties and behaviours. See here for an example of the extreme power of enums in Java.

BlueRaja - Danny Pflughoeft
Yes, it's true that what I want is something like an elaborate enum. But I want dozens of classes with the same elaboration. To the best of my knowledge, I can't subclass an enum. So yes, I could accomplish this by making a whole bunch of enums with identical code. But copy-and-pasting code is a maintenance nightmare. Unless there's a way to subclass an enum, that just won't cut it for me here.
Jay
@Jay: No, you want a *single* enum class, no subclassing involved. Each thing you're using a class for now would actually be an enum value. The custom behaviour for each "class" would actually be an implementation of an abstract enum method, specific to each enum value. Everything shared would simply be part of the enum, like any other class. There would be no copying/pasting involved - the situation you're describing is *exactly* what Java's powerful enums are for.
BlueRaja - Danny Pflughoeft
I think you're misunderstanding my requirement. (Or I'm misunderstanding you.) I'm updating the original question to be more concrete, maybe this will clarify.
Jay
A: 

I would be thinking of a factory method:

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; }
}

Your A wouldn't need all those static methods anymore of course.

extraneon
A: 

You can use the indexes of class, the static list don't need yow can just use the indexes that refer of the instace of these class of cors and the subclass. Here is a excample : http://www.java2s.com/Code/CSharp/Class-Interface/Indexerallowarraylikeindex.htm

Haroldis
A: 

If you need a singleton functionality and at the same time want to get benefit of inheritance you should consider Dependency Injection frameworks such as Spring or PicoContainer. Even if your application is quite small your life still will be easier with a framework managing dependencies.

wax