0

I have a class as below

public abstract class MyObjectManager {
   private final Map<MyKey, MyObject> objects;
   private final MySystem system;
   MyObjectManager(MySystem inputSystem) {
     system = inputSystem;
     // also initialize the "objects" field.
   } 
   public void write(MyKey myKey, MyObject myObject) {...}
   public MyObject read(MyKey myKey) {...}
   public abstract MyObject getNewestObject();
}

I need two types of ConcreteManagers which will have different map implementation, for example,

One uses new LinkedHashMap(CAPACITY_1, LOAD_FACTOR_1, true){ // override the removeEldestEntry(){// logic 1}}.

The other uses new LinkedHashMap(CAPACITY_2, LOAD_FACTOR_2, false){ // override the removeEldestEntry(){// logic 2}}.

I don't want to pass the map as a @param since the map implementation is fixed for each ConcreteManager.

Should I use a strategy pattern or factory pattern to have different map initialization?

Or should I move the objects field to each implementation classes? But their implementation of read and write methods duplicate a lot.

eriee
  • 416
  • 2
  • 15

1 Answers1

2

If I understood your question, it seems to me that you could add the map as a parameter the abstract class, then pass the concrete map instance in the children constructor. For example:

public abstract class MyObjectManager {

    private final Map<MyKey, MyObject> objects;
    private final MySystem system;

    MyObjectManager(final Map<MyKey, MyObject> objects, MySystem inputSystem) {
        this.objects = objects;
        this.system = inputSystem;
    }
}

public class ConcreteManager extends MyObjectManager {
    public ConcreteManager(MySystem inputSystem) {
        super(new LinkedHashMap(CAPACITY_1, LOAD_FACTOR_1, true), inputSystem);
    }
}

This way fulfils your constraints:

  • The Map class is fixed to a concrete manager implementation
  • The objects attribute remains in the parent class
Miguel Jiménez
  • 1,276
  • 1
  • 16
  • 24
  • Good answer, but it'd be a better answer if you kept the original `MySystem` parameter, to show how it is still a parameter to the subclass constructors, and simply passed along to the base class. – Andreas Oct 02 '18 at 22:55
  • 1
    The original constructor was *package-private*, so you should keep that too. There is actually no reason to ever make a constructor of an abstract class `public`, because it can only ever be called from subclasses, so `protected` or *package-private* is more appropriate. The subclass constructor can of course be `public`. – Andreas Oct 02 '18 at 23:04
  • Excellent Andreas, thank you for your observations. I updated the example. – Miguel Jiménez Oct 03 '18 at 00:09