抽象工厂设计模式和泛型 - Java

这是我第一次使用这种设计模式,我遇到了一些困难。以此图为参考:

http://img3.mukewang.com/628d8aa400017aa319201270.jpg

我有两个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 中使用泛型,以便让客户端只使用抽象类而不知道底层实现?


守着星空守着你
浏览 196回答 2
2回答

暮色呼如

您可以将泛型类型添加到ApplicationFactory.public class MainJava {&nbsp; &nbsp; interface Frame{}&nbsp; &nbsp; interface FrameMap<T extends Frame>{}&nbsp; &nbsp; static class App1Frame implements Frame{}&nbsp; &nbsp; static class App2Frame implements Frame{}&nbsp; &nbsp; static class App1FrameMap implements FrameMap<App1Frame>{}&nbsp; &nbsp; static class App2FrameMap implements FrameMap<App2Frame>{}&nbsp; &nbsp; interface ApplicationFactory<T extends Frame> {&nbsp; &nbsp; &nbsp; &nbsp; T makeFrame();&nbsp; &nbsp; &nbsp; &nbsp; FrameMap<T> makeFrameMap();&nbsp; &nbsp; }&nbsp; &nbsp; static class App1Factory implements ApplicationFactory<App1Frame> {&nbsp; &nbsp; &nbsp; &nbsp; @Override public App1Frame makeFrame() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new App1Frame();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override public FrameMap<App1Frame> makeFrameMap() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new App1FrameMap();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String... args) {&nbsp; &nbsp; &nbsp; &nbsp; ApplicationFactory<? extends Frame> factory = new App1Factory();&nbsp; &nbsp; &nbsp; &nbsp; Frame frame = factory.makeFrame();&nbsp; &nbsp; &nbsp; &nbsp; FrameMap<? extends Frame> map = factory.makeFrameMap();&nbsp; &nbsp; }}另请注意,ApplicationFactory应将对象注入客户端。如果客户端直接调用new App1Factory(),那么抽象是没有意义的。客户端还不如App1Factory创建后使用。

jeck猫

除了@jaco0646 解决方案,还有一种简单的方法可以解决将新创建的框架添加到地图的问题,即使您在运行时不知道实际的子类型或“族”。只要您可以将 frame 和 frame-map 类型参数绑定为在方法中具有相同的值,如下所示:public static <T extend Frame> FrameMap<T> makeAndAdd(final AbstractFactory<T> factory) {&nbsp; &nbsp; T frame = factory.makeFrame();&nbsp; &nbsp; FrameMap<T> map = factory.makeFrameMap();&nbsp; &nbsp; map.add(frame);&nbsp; &nbsp; return map;}当不可能将两个动作放在同一个方法中时(例如,在不同的服务器调用上异步发生)。您仍然可以通过使用另一个具有类型参数并且具有这些操作的不同方法的类来实现这种联系......这有点复杂,需要根据实际问题进行调整,但想法是相同的从某种意义上说,您使用类型参数将在运行时赋予不同对象的类型参数值联系起来。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java