Patterns
Beneath others, JTools uses the following patterns:
Helper Pattern
Motivation
In many cases it is desired to deal with immutuable objects. To construct those
objects - maybe in reflective environments (Java-Beans, Ant, DAO ...) - we use
helper classes.
Design
If we have an immutuable class foo with one property Bar:
public class Foo {
private final int bar;
public Foo(int bar) {
this.bar=bar;
}
public int getBar() {
return bar;
}
}
The appropriate helper class would look like this:
public class FooHelper {
private int bar;
public void setBar(int bar) {
this.bar=bar;
}
public Foo toFoo() {
return new Foo(bar);
}
}
Filter Pattern
Motivation
Design
Mapper Pattern
Motivation
Design
Visitor Pattern
Motivation
The Visitor Pattern is used to move functionality out of the object instance and to
avoid switch-case-statements.
Design
Jtools uses a little modified version of the standard visitor pattern to allow
stateless use of visitors in most cases.
If there is an interface Sample with two characteristic values Foo and Bar, the appropriate
Pattern usage would be
//Sample interface
public interface Sample {
//accept method
<R, D> R accept(SampleVisitor<R, D> visitor, D... data);
}
//Implementation Foo
public class Foo implements Sample {
//accept method calls visitFoo
public <R, D> R accept(SampleVisitor<R, D> visitor, D... data) {
return visitFoo(visitor, data);
}
}
//Implementation Bar
public class Bar implements Sample {
//accept method calls visitBar
public <R, D> R accept(SampleVisitor<R, D> visitor, D... data) {
return visitBar(visitor, data);
}
}
//The Visitor interface for Sample
public interface SampleVisitor<R, D> {
//callback hook for Foo
R visitFoo(Foo foo, D... data);
//callback hook for Bar
R visitBar(Bar bar, D... data);
//callback hook for custom Sample characteristics
R visitCustomSample(Sample sample, D... data);
}
//The standard implementation for the visitor
public class SimpleSampleVisitor<R, D> implements SampleVisitor<R, D> {
public R visitFoo(Foo foo, D... data) {
return visitDefinedSample(foo, data);
}
public R visitBar(Bar bar, D... data) {
return visitDefinedSample(bar, data);
}
protected R visitDefinedSample(Sample sample, D... data) {
return visitSample(sample, data);
}
public R visitCustomSample(Sample sample, D... data) {
return visitSample(sample, data);
}
protected R visit(Sample sample, D... data) {
return null;
}
}
A method can now define a singleton visitor instance to calculate values.
public class SampleUtils {
private static class AdjustVisitor extends SampleVisitor<Double, Boolean> {
public Double visitFoo(Foo foo, Boolean... data) {
//using autoboxing
return data[0] ? 2.0 : 2.5 ;
}
public Double visitBar(Bar bar, Boolean... data) {
//using autoboxing
return data[0] ? 1.1 : 0.5;
}
protected Double visit(Sample sample, Boolean... data) {
throw new RuntimeException("unexpected Sample implementation "+sample);
}
}
private static AdjustVisitor adjustVisitor = new AdjustVisitor();
public static Double multiply(Sample sample, boolean extended) {
return sample.accept(adjustVisitor, extended ? Boolean.TRUE : Boolean.FALSE);
}
}