Java 工厂方法与单例设计模式的结合

Java 工厂方法与单例设计模式的结合,java,design-patterns,singleton,factory-pattern,Java,Design Patterns,Singleton,Factory Pattern,我目前正在实施一个游戏,其中有不同类型的地图。作为所有映射,它们自然地共享某些属性和方法,因此创建了一个抽象类Map,然后由诸如SafeMap、HazardousMap、WeirdMap等映射子类 为了便于将来添加更多地图,使用了factory方法设计模式。因此,该程序包含一个MapCreator类,其代码如下所示: 公共类MapCreator{ 公共映射createMap(字符映射类型){ 开关(映射类型){ 案例S: 返回新的SafeMap(); 案例“H”: 返回新的HazardousMa

我目前正在实施一个游戏,其中有不同类型的地图。作为所有映射,它们自然地共享某些属性和方法,因此创建了一个抽象类
Map
,然后由诸如
SafeMap
HazardousMap
WeirdMap
等映射子类

为了便于将来添加更多地图,使用了factory方法设计模式。因此,该程序包含一个
MapCreator
类,其代码如下所示:

公共类MapCreator{
公共映射createMap(字符映射类型){
开关(映射类型){
案例S:
返回新的SafeMap();
案例“H”:
返回新的HazardousMap();
案例“W”:
返回新的古怪地图();
违约:
返回null;
}
}
}
现在我还想强制执行只存在一个Map实例(不管选择了哪个子类)。我已经读过,最好的方法是部署singleton设计模式,其中静态实例在类中被私有声明,构造函数也被私有化。但我不知道如何与工厂方法设计模式结合使用,因为我们有多个子类,
getInstance()
必须在一个具体的类中

我感谢任何帮助



注意:我已经看过了,但我认为这些回答与我的案例无关。

最简单的方法是使用单个静态字段,如果已经创建了映射,则返回该值

代码未经测试,但我认为概念足够简单:

public class MapCreator{
    private static Map theOnlyMap;
    public synchronized Map createMap(char mapType){
        if( theOnlyMap != null ) return theOnlyMap;
        switch(mapType){
            case 'S':
                theOnlyMap = new SafeMap();
                 break;
            case 'H':
                theOnlyMap =  new HazardousMap();
                break;
            case 'W':
                theOnlyMap = new WeirdMap();
                break;
        }
        return theOnlyMap;
    }
}

ServiceLocator模式就是您要寻找的

一般来说,为了避免在任何地方都使用单例,您倾向于使用这种模式,如果必要的话,可以在单元测试中模拟这种模式

它由一个映射组成,该映射将接口类作为键,对象作为值(它可以容纳许多单例类/接口)

因此,您可以使用一个带有hashmap的ServiceLocator,该hashmap的条目以Map.class作为键,所需的实例作为值

您可以通过以下方式获得值(例如):


其中get是封装hashmap.get(Map.class)的通用getter

创建一个映射类型后,是否可以替换该映射类型?如果玩家看的是“安全地图”,那么在某一点上可以用“危险地图”的实例替换吗?@markspace否,一旦玩家选择,地图在整个游戏中都是固定的。最简单的方法是使用一个静态字段,如果已经创建了地图,则返回该值。@markspace您可以在回答中详细说明吗?我不确定我是否明白你的意思。我会使用。我没有使用此设计模式,因为我认为这不是我的作业所期望的(我们在课堂上没有介绍ServiceLocator设计模式)。但是谢谢你的回答,听起来它会起作用。第一次createMap方法将返回这3个地图中的一个,但是对于其余的情况,“onlyMap”将永远不会为空,所以我们不能更改其他地图。请听Luke上面的评论:“不,一旦玩家选择,地图在整个游戏中都是固定的。”@M.ArslanKhanAHH…谢谢你
ServiceLocator.get(Map.class);