Java抽象工厂和单例

Java抽象工厂和单例,java,design-patterns,singleton,factory-pattern,Java,Design Patterns,Singleton,Factory Pattern,我想实现一个抽象工厂的例子,但是具体工厂必须作为单例 以巴纳斯先生为例:我应该修改UFOEnemyShipFactory和UFOBossEnemyShipFactory,对吗 我为UFOEnemyShipFactory尝试了一些东西,但我不确定是否正确: public class UFOEnemyShipFactory implements EnemyShipFactory{ private UFOEnemyShipFactory(){}; private static UF

我想实现一个抽象工厂的例子,但是具体工厂必须作为单例

以巴纳斯先生为例:我应该修改UFOEnemyShipFactory和UFOBossEnemyShipFactory,对吗

我为UFOEnemyShipFactory尝试了一些东西,但我不确定是否正确:

public class UFOEnemyShipFactory implements EnemyShipFactory{

    private UFOEnemyShipFactory(){};

    private static UFOEnemyShipFactory firstInstance = null;

    public static UFOEnemyShipFactory getInstance(){
    
        if(firstInstance == null){
        
            synchronized(UFOEnemyShipFactory.class){
            
                if(firstInstance == null){
                
                    firstInstance = new UFOEnemyShipFactory();
                
                }
            
            }
        
        }
    
        return firstInstance;
    
    }

    public ESWeapon addESGun(){
        return new ESUFOGun();
    }

    public ESEngine addESEingine() {
        return new ESUFOEngine();
    }
这似乎有点奇怪,我认为我没有在正确的类中应用所需的修改。如果我完全错了,你能给我一个简单的解释吗(为什么我错了,我必须修改哪个类,为什么?)


提前谢谢。

恐怕我没有关于AbstractFactory问题的完整信息,但我可以帮助您解决单例问题

通常,当您尝试单例设计模式时,您会指定一个私有构造函数,这样其他人就不能使用默认构造函数来创建自己的实例

作为一个补充观察,您已经进入了经典的“双重检查”反模式(一些不应该做的事情)。我在这里写了更多: 基本上,不要在同步块之外进行检查,先进行同步,然后再次检查。看起来很安全,但事实并非如此。为此:

public static UFOEnemyShipFactory getInstance(){
    if(firstInstance == null){
        synchronized(UFOEnemyShipFactory.class){
            if(firstInstance == null){
                firstInstance = new UFOEnemyShipFactory();
            }
        }
    }
    return firstInstance;
}
写下以下内容之一:

public static synchronized UFOEnemyShipFactory getInstance(){
    if(firstInstance == null){
                firstInstance = new UFOEnemyShipFactory();
    }
    return firstInstance;
}
或者许多人会说:

private static final UFOEnemyShipFactory firstInstance = new UFOEnemyShipFactory();

public static UFOEnemyShipFactory getInstance(){
    return firstInstance;
}

也是一个风格点。从理论上讲,你可以随心所欲地说出事情的名称,“第一个实例”会引发问题。是否有“第二个实例”?但是,“实例”(至少在java意义上)通常意味着“唯一”。最好只是“举例”。如果您的想法是在某个地方有两个单例,但它们是不同的,您可以将它们命名为
ufoBossInstance
ufoGruntInstance
,例如在引用页面的命名之后。

如果您确实想要单例,为什么不使用
enum
?Java语言完成了所有繁重的工作。当然,对于单身汉是否好有很多争议。你的第二个代码帖子毫无意义;您可以只进行一次空检查。重复检查null(至少在理论上)的原因是,您可以在同步之前廉价地执行其中一项检查。@Jason S.是的,谢谢。我的编辑错误…已更正。