Re: How to let the methods of a class only can be invoked by a special
package(the class not in the package)?
Thomas Schodt wrote:
Jebel.Star@gmail.com wrote:
There is a class A in package xx.zz.gg , and A has a static method
A.getInstance(). There are 3 classes B, C, D in package xx.zz
How can I make the A.getInstance() only can be invoked by the B, C and D
class A {
private A() {};
private static final Set allowed = new HashSet() {{
add("xx.zz.B");
add("xx.zz.C");
add("xx.zz.D");
}};
static A a = null;
static A getInstance() {
Class[] ca = new SecurityManager() {
protected Class[] getClassContext() {
return super.getClassContext();
}
}.getClassContext();
// ca[0] is the anonymous security manager
// ca[1] is this class ("A")
// ca[2] is the calling class
if (!allowed.contains(ca[2].getName())) {
throw new InstantiationError("Not allowed from "+ca[2]);
}
if (a==null) { a = new A(); }
return a;
}
}
That's a great pattern. Take it a step further and store a
Map <String, Class <? extends Allowed>>
or a Map <AllowedEnum, Class <? extends Allowed>>
where 'Allowed' is a supertype for the classes that are allowed. The 'String'
or 'AllowedEnum' enum identify the particular implementing class for each case
you want to permit.
For that matter, you could craft an 'AllowedEnum' where each enum instance's
behavior does what you want - that could well be your optimal solution in that
it gives you compile-time safety on the behaviors, not merely run-time checks.
From a maintenance standpoint, such an enum collects verification of an
action's legality and its activity into a single class, binding them at
compile time, making life easier.
The downside to the enum implementation is that you have to recompile the
world to extend the behaviors. If runtime configurability is what you need,
then you need a runtime technique such as the ServiceProvider pattern.
--
Lew