views:

218

answers:

2

The following Java design allows an object to be extended without changing its interface to clients. The object can implement additional extension interfaces. Clients can ask the object for extension interfaces that it implements. I read about it in a blog post, but my Google skills failed to find the blog post again. I'm not advocating the merits of this design. I just want to find the blog post.

For example, imagine a domain model for transportation vehicles. Every vehicle object implements this interface:

public interface Extendable {

    /**
     * Asks the object if it provides the extension.
     * 
     * @param extensionInterface
     *            requested extension
     * @return object implementing the requested extension, or {@code null} if
     *         not available.
     */
    <T> T queryExtension(Class<T> extensionInterface);
}

Fixed wing aircraft have flight control surfaces but other types of vehicles don't. Define a interface for the control surfaces feature:

public interface ControlSurfaces {
    String getAilerons();
    String getElevator();
    String getRudder();
}

The fixed wing aircraft class provides the ControlSurfaces extension:

public class FixedWingAircraft extends Vehicle {

    @SuppressWarnings("unchecked")
    public <T> T queryExtension(Class<T> extensionInterface) {
        if (ControlSurfaces.class.equals(extensionInterface)) {
            return (T) new ControlSurfacesImpl();
        }
        return null;
    }
}

Suppose the domain model is an anemic domain model, so a service object is responsible for saving vehicle objects to persistent storage. The service must ask the vehicle for extension interfaces which must also be saved.

public class VehicleServiceImpl {

    private VehicleDao vehicleDao;
    private ControlSurfacesDao controlSurfacesDao;

    public void save(Vehicle vehicle) {
        vehicleDao.save(vehicle);

        ControlSurfaces controlSurfaces = vehicle.queryExtension(ControlSurfaces.class);
        if (controlSurfaces != null) {
            controlSurfacesDao.save(vehicle, controlSurfaces);
        }
    }
}
A: 

Do you mean using proxies to expose an interface at runtime? Sorry, but your question is confusing. I don't see how bringing up anemic domain model is helping matters.

duffymo
I mentioned anemic domain model for the sake of the example. The Vehicle class is anemic because it does not know how to persist itself. A separate service class implements the persistence functionality. Therefore the service class must know all the extensions to the Vehicle class which need to be persisted. An anemic domain model is irrelevant to the Extension Interface pattern.
Jim Huang
+1  A: 

This is a Java instance of the "Extension Interface" pattern, as presented in the "Pattern-Oriented Software Architecture" Vol. 2 (POSA-2), by Schmidt, Stal, Rohnert and Buschmann, Wiley, 2000.

Pascal