001package composite.three;
002
003public class ExprFactory2 {
004        private ExprFactory2() {}
005        static public Expr newConst(int v) {
006                return new Const(v);
007        }
008        static public Expr newPlus(Expr l, Expr r) {
009                return new PlusOp(l, r);
010        }
011//      static public Expr newMinus(Expr l, Expr r) {
012//              return new BinOp(l, new OpSub(), r);
013//      }
014//      static public Expr newMult(Expr l, Expr r) {
015//              return new BinOp(l, new OpMul(), r);
016//      }
017//      static public Expr newQuot(Expr l, Expr r) {
018//              return new BinOp(l, new OpDiv(), r);
019//      }
020
021        private static final class Const implements Expr {
022                private final int v;
023                public Const(int v) {
024                        this.v = v;
025                }
026                public int eval() {
027                        return v;
028                }
029                public String toString() {
030                        return Integer.toString(v);
031                }
032        }
033
034        private static abstract class BinOp implements Expr {
035                private final Expr l;
036                private final Expr r;
037                private final String opString;
038                public BinOp(Expr l, String opString, Expr r) {
039                        if ((l == null) || (r == null)) {
040                                throw new IllegalArgumentException();
041                        }
042                        this.l = l;
043                        this.r = r;
044                        this.opString = opString;
045                }
046                protected abstract int run (int x, int y);
047                // to be template method, there must a template method
048                // template method = method of abstract class, that calls an abstract method
049                public int eval() {
050                        return this.run(l.eval(), r.eval());
051                }
052                public String toString() {
053                        return l.toString() + " " + r.toString() + " " + opString;
054                }
055        }
056        private static final class PlusOp extends BinOp {
057                public PlusOp(Expr l, Expr r) { super (l, "+", r); }
058                public int run(int x, int y) { return x+y; }
059        }
060}
061