繁体   English   中英

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

[英]Abstract factory design pattern and generics - Java

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

在此处输入图片说明

我有两个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);
    }
    ...
}

请注意, FrameMapF的集合(为简单起见,我省略了大多数其他方法),因此它需要能够获取和放置元素。 以一个家庭为例(App1的一个)为具体产品

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只使用抽象类而不知道底层实现?

您可以将泛型添加到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对象注入客户端。 如果客户端直接调用new App1Factory() ,则没有指向抽象的意义。 客户端可能在创建App1Factory之后也可以使用它。

除了@ 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;
}

当不可能将两个动作都放在相同的方法中时(例如,在不同的服务器调用上异步发生)。 您仍然可以通过使用带有类型参数的另一个类来实现这种联系,这些类具有不同的操作方法……这有点复杂,需要针对实际问题进行量身定制,但是想法是相同的从某种意义上说,您是在运行时使用类型参数来绑定给不同对象的类型参数值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM