It's the first time I'm using this design pattern and I'm having some difficulties. Taking this image as reference:
I have two AbstractProduct that I would like to create a factory for, since they come in different "families". One of the products is a collection of the other.
public abstract class Frame{
...
}
public abstract class FrameMap<F extends Frame>{
protected TreeMap<Integer, F> map;
public F readByKey(Integer key){
return this.map.get(key);
}
public void put(Integer key, F frame){
this.map.put(key,frame);
}
...
}
Note that FrameMap
is a collection of F
(I omitted most of the other methods for simplicity), so it needs to be able to get and put elements.
Taking one family as an example (the one for App1) these are the concrete Product:
public class App1Frame extends Frame{
...
}
public class App1FrameMap extends FrameMap<App1Frame>{
...
}
Then I have created the AbstractFactory:
public abstract class ApplicationFactory{
//Frame factory methods
public abstract Frame makeFrame();
//FrameMap factory methods
public abstract FrameMap<? extends Frame> makeFrameMap();
}
And the ConcreteFactory for App1:
public class App1Factory extends ApplicationFactory{
//Frame factory methods
public Frame makeFrame(){
return new App1Frame();
}
//FrameMap factory methods
public FrameMap<App1Frame> makeFrameMap(){
return new App1FrameMap();
}
}
All of this compiles, but I'm not liking it very much because my Client cannot do something like:
ApplicationFactory factory = new App1Factory();
FrameMap<Frame> frameMap = factory.makeFrameMap(); //This doesn't compile!
which is, at least conceptually, the goal of the pattern, i.e. letting the client only use the abstract classes. In order to make it work, I have to do something like this:
App1Factory factory = new App1Factory();
FrameMap<App1Frame> frameMap = factory.makeFrameMap(); //This compiles!
which seems going against the purpose of using the design pattern.
Do you know any better way of implementing this pattern in a situation like mine, i.e. using generics in the AbstractProduct, in order to let the Client only use the abstract classes without knowing the underlying implementation?