Я впервые использую этот шаблон проектирования , и у меня возникают некоторые трудности. Принимая это изображение в качестве ссылки:
У меня есть два AbstractProduct , для которых я хотел бы создать фабрику, поскольку они принадлежат к разным «семьям». Один из продуктов представляет собой коллекцию другого.
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);
}
...
}
Обратите внимание, что FrameMap
- это набор F
(я упустил большинство других методов для простоты), поэтому он должен иметь возможность получать и размещать элементы.
Если взять в качестве примера одну семью (одну для App1), это конкретный Product :
public class App1Frame extends Frame{
...
}
public class App1FrameMap extends FrameMap<App1Frame>{
...
}
Затем я создал AbstractFactory :
public abstract class ApplicationFactory{
//Frame factory methods
public abstract Frame makeFrame();
//FrameMap factory methods
public abstract FrameMap<? extends Frame> makeFrameMap();
}
И ConcreteFactory для 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();
}
}
Все это компилируется, но мне это не очень нравится, потому что мой Клиент не может сделать что-то вроде:
ApplicationFactory factory = new App1Factory();
FrameMap<Frame> frameMap = factory.makeFrameMap(); //This doesn't compile!
что является, по крайней мере, концептуально, целью паттерна, то есть позволить клиенту использовать только абстрактные классы. Чтобы заставить это работать, я должен сделать что-то вроде этого:
App1Factory factory = new App1Factory();
FrameMap<App1Frame> frameMap = factory.makeFrameMap(); //This compiles!
что противоречит цели использования шаблона проектирования.
Знаете ли вы какой-нибудь лучший способ реализации этого шаблона в такой ситуации, как у меня, то есть с использованием обобщений в AbstractProduct, чтобы позволить Клиенту использовать только абстрактные классы, не зная базовой реализации?