The
RosettaPattern for defining and instantiating
CommonLisp types has proven to be very robust in handling basic and array types. But the demands of the
DefstructType? and the evn more complex
ClosClassType? have pushed us to extend the basic
RosettaPattern to encompass the
AbstractFactoryPattern? (Gamma et al). These complex types require the ability to replace the nested
Factory class at runtime without sacrificing the in-situ type Java interface.
The basic
RosettaPattern defines a public interface with a nested public static factory class that constructs instances of the type. For example
public interface lisp.common.type.Integer {
public static class Factory {
public static lisp.common.type.Integer newInstance(int value) {
... code to create a Lisp Integer from the Java int ...
}
}
}
Once the interface is loaded, there is no mechanism (excluding the Java debugger) to alter the Factory class at runtime.
Core Abstract Pattern
Some complex
CommonLisp types may be redefined at runtime in ways that are incompatible with the initial definition of the type. For example, a structure type -
FOO - created by Defstruct can be completely altered (number, names, and types of slots) dynamically. Once that change is made, the constructor function, e.g.
MAKE-FOO, will now produce instances of the new definition. Note that prior instances of
FOO are still of type
FOO, and the original accessor functions still work correctly with the older instances. The same will be true for a Java programmer. Both new and old instances are of the same Java type - for example -
edu.cofc.cs.ServerArray.
The core pattern creates a level of indirection consistent with the constraints of the JVM. The pattern adds an additional nested static class of type
AbstractFactory? . This class has no executable code but does possess a field that holds an instance of the appropriate factory type for the Lisp type. The type interface holds an instance of this
AbstractFactory? . Since this is within an interface, it is a static final field (not changeable after class initialization).
The second component of the core pattern is the implementing class for the type. This class also possesses a static Factory class that produces instances of itself. The Factory class is of the same type as the
AbstractFactory? defined in the type interface. To set this class as the current definition of the type just requires making an instance of the implementing class's Factory class and setting it in the field of the
AbstractFactory? referenced in the type interface.
An example is in order...
| Type Interface |
public interface MyStruct {
public static final MyStruct.AbstractFactory factory = new MyStruct.AbstractFactory();
public static class Factory {
public static MyStruct newInstance(Object... args) {
return factory.trueFactory.newInstance(args);
}
}
public static class AbstractFactory {
// DefstructFactory is a simple interface that simplifies and
// standardizes the Factory signature
DefstructFactory trueFactory = null;
}
}
|
| Implementing Class |
public class MyStructImpl implements MyStruct {
public static final MyStructImpl.Factory trueFactory = new MyStructImpl.Factory();
public static class Factory implements DefstructFactory {
public Defstruct newInstance(Object... args) {
return new MyStructImpl(args);
}
}
... implementing code goes here ...
}
|
DefstructType? Implementation
This section fills in some of the details pertinent to the Defstruct implementation. For convenience, common code across all
Defstruct implementations are defined by a public interface
Defstruct and an abstract class
DefstructImpl.
Particular to
Defstruct is the static code in the
FooStructImpl class. This code is executed when the class is initialized. The static code automatically sets its Factory as the concrete Factory that will be used by the
FooStruct interface. Greedy little things these
DefstructImpls? ...
| Type Interface |
public interface FooStruct extends Defstruct {
public static final FooStruct.AbstractFactory factory = new FooStruct.AbstractFactory();
public static class Factory {
public static FooStruct newInstance(Object... args) {
return factory.trueFactory.newInstance(args);
}
}
public static class AbstractFactory {
// DefstructFactory is a simple interface that simplifies and
// standardizes the Factory signature
DefstructFactory trueFactory = null;
}
}
|
| Implementing Class |
public class FooStructImpl extends DefstructImpl implements FooStruct {
public static final FooStructImpl.Factory trueFactory = new FooStructImpl.Factory();
static { FooStruct.factory.trueFactory = trueFactory; }
public static class Factory implements DefstructFactory {
public Defstruct newInstance(Object... args) {
return new FooStructImpl(args);
}
}
... implementing code goes here ...
}
|
Extending the
FOO defstruct in Lisp is a bit tricky in the Java realm. For the complete architecture, see
DefstructImplementation? . Here is just shown the type inheritence when creating a new structure
BAR that extends
FOO.
| Subtype Interface |
public interface BarStruct extends FooStruct {
public static final BarStruct.AbstractFactory factory = new BarStruct.AbstractFactory();
public static class Factory {
public static Defstruct newInstance(Object... args) {
return factory.trueFactory.newInstance(args);
}
}
public static class AbstractFactory {
DefstructFactory trueFactory = null;
}
}
|
| Implementing Class |
public class BarStructImpl extends DefstructImpl implements BarStruct {
public static final BarStructImpl.Factory trueFactory = new BarStructImpl.Factory();
static { BarStruct.factory.trueFactory = trueFactory; }
public static class Factory implements DefstructFactory {
public Defstruct newInstance(Object... args) {
return new BarStructImpl(args);
}
}
... implementing code goes here ...
}
|
Note that the type inheritence is defined by the interface inheritence, not implementing class inheritence. While
BarStruct is a
FooStruct, a
BarStructImpl is not a
FooStructImpl.
ClosClassType? Implementation
--
JerryBoetje - 01 Apr 2006