将类的实例化限制为单个Factory

时间:2011-05-16 11:56:01

标签: java design-patterns

我有一个类,我想将其实例化限制为只有一个Factory类,如何防止这个对象被new运算符实例化?

6 个答案:

答案 0 :(得分:4)

使所有构造函数包都是私有的;在同一个包中有一个Factory对象,它拥有包外的客户端的公共创建方法。

使用单个类很容易,但我想你要将该Factory视为虚拟:能够创建单个接口或抽象类的多个实现。

答案 1 :(得分:1)

您可以使类成为工厂类的内部(成员)类。单例工厂实例只能在工厂类中访问。工厂方法应该返回由内部类实现的公共接口。

public interface FooBehavior { ... }
public class FooFactory {
    private static FooFactory factory = new FooFactory();
    private FooFactory() { ... }
    class Foo implements FooBehavior { ... }
    public static FooBehavior createFoo() {
        return factory.new Foo();
    }
}

Foo的实例与工厂的生命周期相关联。因为工厂的实例需要创建Foo的实例,并且因为工厂的唯一实例包含在工厂中,所以只有工厂可以创建Foo的实例。

另外,使用单例模式时要小心。

答案 2 :(得分:1)

根据你的问题,Jigar是正确的,但是,这是一种具有严重缺陷的反模式:

http://en.wikipedia.org/wiki/Singleton_pattern#Drawbacks

http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx

我建议您在实施此类解决方案之前先查看系统的设计。永远不需要以你所描述的方式锁定类的实例化。

答案 3 :(得分:1)

更简单的方法是信任同一个包中的其他类。

这样构造函数具有默认范围,而Factory必须位于同一个包中。


但是要回答你的问题,你可以使Factory成为一个内部类,它可以调用外部类的私有构造函数。 e.g。

public class MyObject {
    private MyObject() { }

    public static class Factory {
         public MyObject create() {
             // can call private members of the outer class.
             return new MyObject(); 
         }
    }
}

MyObject.Factory mof = new MyObject.Factory();
MyObject mo = mof.create();

使用此方法限制对内部和嵌套类的访问。

答案 4 :(得分:0)

这并不容易。您可以将构造函数包本地化,然后将工厂置于同一个包中。这仍然意味着在同一个包中定义的类仍然可以实例化该类。

您可以通过执行类似 -

的操作来查询当前线程中的堆栈
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if ("your.package.Factory".equals(stackTrace[1].getClassName()) {
    instantiateClass();
} else {
    throw new InstantiationException("Can only instantiate from factory");
}

你必须检查它是哪个StackTraceElement,但这应该有效。

答案 5 :(得分:0)

另一种开始替换Singleton模式的模式是使用枚举:

public enum Factory { INSTANCE;

  public SomeObject create(Params someParams) {
    if (isTypeA(someParams))
      return new TypeASubclass();
    else if (isTypeB(someParams))
      return new TypeBSubclass();
    else
      return new SomeDefaultObject();
  }
}

您将以标准方式使用它:

SomeObject someObject = Factory.INSTANCE.create(myParams);

enum保证系统上只有一个工厂 *)


*)通常每个jvm /每个类加载器一个限制