In a previous article, I described a Concealed Controller Pattern, which allows Java classes to be packaged separately, while maintaining access control to certain sensitive methods. In today’s article, I discuss the shortcomings of Java’s package capabilities and present a simple pattern (the Keyed Access Pattern) for overcoming one case.

Motivation: The Java Programming Language allows classes within the same package to access one another’s package-protected methods. This allows related classes to have special access, without exposing those methods publicly. Oftentimes it is desirable to further group related classes into a package hirarchy.

Unfortunately, the Java Programming Language does not have any actual notion of a sub-package; all packages define a unique namespace, regardless of the implied naming hierarchy. For example, a package named parent.child is in no way a sub-package of the parent package; they are two entirely different packages, according to the Java Language Specification. Under that rule, Java cannot offer any special-case class or method accessors for sub-packages.

Suppose your parent.child classes have methods that should only be accessible by parent classes, such as Child.give(Candy). In Java, this method must be public for any class outside parent.child to access.

One solution is to create a base class in the parent package, which the parent.child.Child class extends. However, for the purposes of this example, assume that inheritance is not a viable option for the Child class.

Keyed Access Pattern: To avoid strangers giving a Child candy, require a Permission (key) object be passed in: Child.give(Permission,Candy). Permission has a package-protected constructor in the parent package. This enforces that only a parent-packaged class can give candy to a Child (so long as no parent gives out its Permission). The child must always validate that the permission is non-null. Through this pattern, the Child class can be packaged separate from parents, and still provide a public method for receiving candy, which only parents can access.

Pseudocode:

package parent;
public final class Permission 
{
    Permission() { } // package-protected constructor
}
 
package parent;
public final class Parent
{
    private final Permission key = new Permission();
    public Parent() { }
 
    // although the child's candy method is public,
    // only a parent can construct a key for access;
    // the following public method can enforce logic
    // required to safely give a child candy
    public void offer(Candy candy) {
        if (safeToEat(candy)) { child.give(key, candy); }
    }
}
 
package parent.child;
public final class Child
{
    public Child() { } 
    public void give(Permission p, Candy c) {
        if (p != null) { eat(c); }
    }
}

Acute practitioners of software design will recognize that this pattern produces a circular package dependency. That is, in this example, the parent.Parent depends on parent.child.Child and parent.child.Child depends on parent.Permission. Thus, the parent and child packages each depend on classes from one another. Java itself has no problem with this, but it is generally viewed as poor programming practice. Although I tend to be rather strict about such things, I consider this case to be acceptable, because it is necessary to enforce a condition not provided by the language: cross-package protected access.

In practice, I only employ this pattern in simple conditions. Breaking down a large package into many (pseudo-)sub-packages would require littering the child class methods with key objects, to enforce parent-only access. The most elegant solution would be an addition to the Java Language Specification, allowing for true hierarchical namespaces, but that is a discussion for another day…

Share and Enjoy:
  • StumbleUpon
  • Facebook
  • Twitter
  • Digg
  • del.icio.us
  • Reddit
  • Technorati
  • Google Bookmarks
  • Slashdot
  • N4G