1

I have a series of classes, A,B,C... (several dozen in total) that share common code. There can be many instance of each class A,B,C... . I'm planning to create a superclass, Abstract, that will contain that code instead.

Problem is, the common stuff works on an object that is unique on a per-class (not per-instance) basis. This is currently solved by A,B,C... each having a static field with the corresponding value. Obviously, when I refactor the functionality into Abstract, this needs to be changed into something else.

In practice, it currently looks like this (note that the actual type is not String, this is just for demonstrative purposes) :

public class A implements CommonInterface {

    private static final String specificVar = "A";

    @Override
    public void common() {
        specificVar.contains('');
    }
}
public class B implements CommonInterface {

    private static final String specificVar = "B";

    @Override
    public void common() {
        specificVar.contains('');
    }
}

The best idea I've come up with until now is to have a Map<Class<? extends Abstract>,K> (where K is the relevant type) static field in Abstract, and A,B,C... each containing a static initalization block that places the relevant value into the map. However, I'm not convinced this is the best that can be done.

Note that I'm not using any DI framework.

So, what would be the most concise, in terms of code contained in the subclasses, way to refactor the static fields in A,B,C... handled by the common code, without sacrificing field access efficiency?

mikołak
  • 9,605
  • 1
  • 48
  • 70

3 Answers3

0

Perhaps an enum is what you want.

enum MyInstances implements MyInterface {
    A {
       fields and methods for A
    }, B {
       fields and methods for B
    };
    common fields for all MyInstances 

    common methods for all MyInstances 
}

// To lookup an instance
MyInstances mi = MyInstances.valueOf("A");
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Problem is, there can be many instances of `A`,`B`,`C`... each. I'll edit my question to clarify that. – mikołak Aug 08 '12 at 12:22
0

As you haven't shown any source code, we can't really tell if the use of static fields is a good or a bad design choice.

Considering the use of static fields by the subclasses is indeed a good design choice, the first way of having common code in a superclass to access them is by calling abstract methods that would be implemented in the subclasses.

Example:

public abstract class SuperClass {
    public void processCommonLogic() {
        // Common logic

        // Execute specific logic in subclasses
        processSpecificLogic();
    }

    public abstract void processCommonLogic();
}

public class ASubClass extends SuperClass {
    public static int SPECIFIC_SUBCLASS_CONSTANT = 0;

    public void processSpecificLogic() {
        // Specific subclass logic
        doSomethingWith(ASubClass.SPECIFIC_SUBCLASS_CONSTANT);
    }
}
Filipe Fedalto
  • 2,540
  • 1
  • 18
  • 21
0

You could use the Template Method Pattern.

Have an abstract method getValue() defined in your abstract class and used within your abstract class wherever you require the value. Then each of your subclasses simply need to implement the getValue method and return the correct value for that subclass.

DB5
  • 13,553
  • 7
  • 66
  • 71
  • Yes, that's one option I considered - the problem is that each subclass would have to contain the same boilerplate code, in the simplest case return the value of a private static field. I'd like to aim for something less redundant. Unless you have a specific idea that avoids that problem? – mikołak Aug 08 '12 at 12:38
  • I'm not sure there is a way to really avoid this boilerplate code (at least not when using a template method for this case). You could potentially use reflection to access the static fields - [as shown in this post](http://stackoverflow.com/questions/850148/accessing-java-static-final-ivar-value-through-reflection), but that could get very messy.... – DB5 Aug 08 '12 at 12:46
  • ...and inefficient, which is contrary to my other requirement. Thanks anyway :). – mikołak Aug 08 '12 at 13:01