这是我第一次使用this design pattern,但遇到了一些困难。以这张图片为参考:
我有两个要创建工厂的 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();
}
和App1的 ConcreteFactory :
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中使用泛型,以便让Client只使用抽象类而又不知道底层实现?
答案 0 :(得分:0)
您可以将通用类型添加到ApplicationFactory
。
public class MainJava {
interface Frame{}
interface FrameMap<T extends Frame>{}
static class App1Frame implements Frame{}
static class App2Frame implements Frame{}
static class App1FrameMap implements FrameMap<App1Frame>{}
static class App2FrameMap implements FrameMap<App2Frame>{}
interface ApplicationFactory<T extends Frame> {
T makeFrame();
FrameMap<T> makeFrameMap();
}
static class App1Factory implements ApplicationFactory<App1Frame> {
@Override public App1Frame makeFrame() {
return new App1Frame();
}
@Override public FrameMap<App1Frame> makeFrameMap() {
return new App1FrameMap();
}
}
public static void main(String... args) {
ApplicationFactory<? extends Frame> factory = new App1Factory();
Frame frame = factory.makeFrame();
FrameMap<? extends Frame> map = factory.makeFrameMap();
}
}
还要注意,ApplicationFactory
对象应该injected进入客户端。如果客户端直接调用new App1Factory()
,则没有指向抽象的意义。客户端在创建App1Factory
之后也可以使用它。
答案 1 :(得分:0)
在@ jaco0646解决方案中,有一种简单的方法可以解决将新创建的框架添加到地图的问题,即使您在运行时不知道实际的子类型或“家庭”。只要您可以将frame和frame-map类型参数都绑定为在这样的方法中具有相同的值:
public static <T extend Frame> FrameMap<T> makeAndAdd(final AbstractFactory<T> factory) {
T frame = factory.makeFrame();
FrameMap<T> map = factory.makeFrameMap();
map.add(frame);
return map;
}
当不可能将两个动作都放在同一方法中时(例如,在不同的服务器调用中异步发生)。您仍然可以通过使用带有类型参数的另一个类来实现这种联系,这些类具有不同的操作方法……这有点复杂,需要针对实际问题进行量身定制,但是想法是相同的在某种意义上说,您是在运行时使用类型参数来绑定给不同对象的类型参数值。