Reputation: 7729
I have a class and I would like to restrict its instantiation to only one Factory class, how can I prevent this object from instantiation by the new operator?
Upvotes: 1
Views: 5650
Reputation: 114817
Another pattern that starts replacing the Singleton pattern is using enums:
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();
}
}
You'll use it in the standard way:
SomeObject someObject = Factory.INSTANCE.create(myParams);
and the enum
gurantees that there is only one factory on the system *)
*) with usual one-per-jvm / one-per-classloader limitations
Upvotes: 0
Reputation: 533870
A simpler approach is to trust other class in the same package.
This way the constructor has default scope and the Factory has to be in the same package.
However to answer your question, you can make the Factory an inner class it can call the private constructor of an outer class. 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();
Using this approach restricts access to inner and nested classes.
Upvotes: 1
Reputation: 13051
You can make the class an inner (member) class of the factory class. The singleton factory instance should be accessible only within the factory class. The factory method should return a public interface implemented by the inner class.
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();
}
}
The instances of Foo
are tied to the lifecycle of the factory. Because an instance of the factory is required to create an instance of Foo
, and because the only instance of the factory is contained within the factory, only the factory can create instances of Foo
.
As an aside, be careful when using the singleton pattern.
Upvotes: 1
Reputation: 3559
Jigar is correct given your question, however, this is an anti-pattern with serious drawbacks:
http://en.wikipedia.org/wiki/Singleton_pattern#Drawbacks
http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
I would suggest that you have a look at the design of the system before you implement such a solution. It should never be necessary to lock instantiation of a class away in the way you descibed.
Upvotes: 1
Reputation: 888
It's not going to be easy. You could make the constructor package local and then situate the factory in the same package. This would still mean that classes defined in the same package could still instantiate that class.
You could interrogate the stack from the current thread by doing something like -
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if ("your.package.Factory".equals(stackTrace[1].getClassName()) {
instantiateClass();
} else {
throw new InstantiationException("Can only instantiate from factory");
}
You'll have to check which StackTraceElement it is, but this should work.
Upvotes: 0
Reputation: 309008
Make all the constructors package private; have a single Factory object in that same package that owns the public creation method for clients outside the package.
It's easy to do with a single class, but I'm imagining that you'd like that Factory to be virtual: able to create several implementations of a single interface or abstract class.
Upvotes: 5