One way to add state is to use your own reference data structure (list). but it uses a visitor pattern and does more than you probably want. this code is rewritten from Little Java, several templates
// a self referential data structure with different types of nodes abstract class Pie { abstract Object accept(PieVisitor ask); } class Bottom extends Pie { Object accept(PieVisitor ask) { return ask.forBottom(this); } public String toString() { return "crust"; } } class Topping extends Pie { Object topping; Pie rest; Topping(Object topping,Pie rest) { this.topping=topping; this.rest=rest; } Object accept(PieVisitor ask) { return ask.forTopping(this); } public String toString() { return topping+" "+rest.toString(); } } //a class to manage the data structure interface PieManager { int addTopping(Object t); int removeTopping(Object t); int substituteTopping(Object n,Object o); int occursTopping(Object o); } class APieManager implements PieManager { Pie p=new Bottom(); // note: any object that implements a rational version of equal() will work public int addTopping(Object t) { p=new Topping(t,p); return occursTopping(t); } public int removeTopping(Object t) { p=(Pie)p.accept(new RemoveVisitor(t)); return occursTopping(t); } public int substituteTopping(Object n,Object o) { p=(Pie)p.accept(new SubstituteVisitor(n,o)); return occursTopping(n); } public int occursTopping(Object o) { return ((Integer)p.accept(new OccursVisitor(o))).intValue(); } public String toString() { return p.toString(); } } //these are the visitors interface PieVisitor { Object forBottom(Bottom that); Object forTopping(Topping that); } class OccursVisitor implements PieVisitor { Object a; OccursVisitor(Object a) { this.a=a; } public Object forBottom(Bottom that) { return new Integer(0); } public Object forTopping(Topping that) { if(that.topping.equals(a)) return new Integer(((Integer)(that.rest.accept(this))).intValue()+1); else return that.rest.accept(this); } } class SubstituteVisitor implements PieVisitor { Object n,o; SubstituteVisitor(Object n,Object o) { this.n=n; this.o=o; } public Object forBottom(Bottom that) { return that; } public Object forTopping(Topping that) { if(o.equals(that.topping)) that.topping=n; that.rest.accept(this); return that; } } class RemoveVisitor implements PieVisitor { Object o; RemoveVisitor(Object o) { this.o=o; } public Object forBottom(Bottom that) { return new Bottom(); } public Object forTopping(Topping that) { if(o.equals(that.topping)) return that.rest.accept(this); else return new Topping(that.topping,(Pie)that.rest.accept(this)); } } public class TestVisitor { public static void main(String[] args) { // make a PieManager PieManager pieManager=new APieManager(); // add some toppings pieManager.addTopping(new Float(1.2)); pieManager.addTopping(new String("cheese")); pieManager.addTopping(new String("onions")); pieManager.addTopping(new String("cheese")); pieManager.addTopping(new String("onions")); pieManager.addTopping(new String("peperoni")); System.out.println("pieManager="+pieManager); // substitute anchovies for onions int n=pieManager.substituteTopping(new String("anchovies"),new String("onions")); System.out.println(n+" pieManager="+pieManager); // remove the 1.2's n=pieManager.removeTopping(new Float(1.2)); System.out.println(n+" pieManager="+pieManager); // how many anchovies do we have? System.out.println(pieManager.occursTopping(new String("anchovies"))+" anchovies"); } }
source share