Interpreter模式和Visitor模式
本文解决我的某个未解之谜:
http://cloverprince.iteye.com/blog/336641
说一个笑话:请问,Java语言的使用者看到了如下的代码会怎么想:
int calculate(int a, int b, char op){ int c; switch(op) { case '+': c=a+b; break; case '-': c=a-b; break; case '*': c=a*b; break; case '/': if (b==0) { errno=1; return -1; } else { c=a/b; break; } } return c;}abstract class Calculator { int calculate(int a, int b);}class Adder extends Calculator { int calculate(int a, int b) { return a+b; }}class Subtracter extends Calculator { int calculate(int a, int b) { return a-b; }}class Multiplier extends Calculator { int calculate(int a, int b) { return a*b; }}class Divider extends Calculator { int calculate(int a, int b) { if(b==0) throw newDivideByZeroException(); else return a+b; }}public abstract class Expression {public abstract double evaluate();}class Constant extends Expression {private double num;public Constant(double num) { this.num = num; }public @Override double evaluate() { return num; }}class AddOperator extends Expression {private Expression lhs, rhs;public AddOperator(Expression lhs, Expression rhs) {this.lhs = lhs;this.rhs = rhs;}public @Override double evaluate() {return lhs.evaluate() + rhs.evaluate(); }}Expression expr = new AddOperator ( new Constant(5.0), new AddOperator( new Constant(3.0), new Constant(2.0) ));expr.evaluate(); // 返回 10
class SubtractOperator extends Expression {private Expression lhs, rhs;public SubtractOperator(Expression lhs, Expression rhs) {this.lhs = lhs;this.rhs = rhs;}public @Override double evaluate() {return lhs.evaluate() - rhs.evaluate(); }}public abstract class Shape {public abstract double getPerimeter();public abstract double getArea();}class Rectangle extends Shape {private Point topLeft;private Point bottomRight;public Rectangle(Point topLeft, Point bottomRight) {this.topLeft = topLeft;this.bottomRight = bottomRight;}@Overridepublic double getArea() {return (bottomRight.x - topLeft.x) * (bottomRight.y - topLeft.y);}@Overridepublic double getPerimeter() {return 2.0 * ((bottomRight.x - topLeft.x) + (bottomRight.y - topLeft.y));}}class Circle extends Shape {private Point center;private double radius;public Circle(Point center, double radius) {this.center = center;this.radius = radius;}@Overridepublic double getArea() {return Math.PI * radius * radius;}@Overridepublic double getPerimeter() {return 2.0 * Math.PI * radius;}}class Triangle extends Shape {private Point p1, p2, p3;public Triangle(Point p1, Point p2, Point p3) {this.p1 = p1;this.p2 = p2;this.p3 = p3;}@Overridepublic double getArea() {return 0.5 * Math.abs(p1.x * p2.y - p2.x * p1.y + p2.x * p3.y - p3.x* p2.y + p3.x * p1.y - p1.x * p3.y);}@Overridepublic double getPerimeter() {return Math.hypot(p1.x - p2.x, p1.y - p2.y)+ Math.hypot(p2.x - p3.x, p2.y - p3.y)+ Math.hypot(p3.x - p1.x, p3.y - p1.y);}}public abstract class Shape {public abstract double getPerimeter();public abstract double getArea();public abstract Point getCenter();}class Rectangle extends Shape {/* more methods omitted */@Overridepublic Point getCenter() {return new Point((topLeft.x + bottomRight.x) / 2.0,(topLeft.y + bottomRight.y) / 2.0);}}class Circle extends Shape {/* more methods omitted */@Overridepublic Point getCenter() {return center;}}class Triangle extends Shape {/* more methods omitted */@Overridepublic Point getCenter() {return new Point((p1.x + p2.x + p3.x) / 3, (p1.y + p2.y + p3.y) / 3);}}class Circle extends Shape { Point getCenter() { /* ..... */ } public @Override Rect getBound() { /* ..... */ } public @Override void draw(CDC dc) { /* ..... */ } public @Override void save(OutputStream ost) { /* ..... */ } public @Override void onMouseLeftButtonClicked() { /* ..... */ } public @Override void onMouseMiddleButtonClicked() { /* ..... */ } public @Override void onMouseRightButtonClicked() { /* ..... */ } public @Override Response request(Request req) { /* ..... */ } public @Override void aMethod() { /* ..... */ } public @Override void anotherMethod() { /* ..... */ } public @Override void yetAnotherMethod() { /* ..... */ } public @Override void yetYetAnotherMethod() { /* ..... */ } public @Override void moreMethodHere() { /* ..... */ } public @Override void yeahTheLastmethod() { /* ..... */ }}public class ShapeVisitor {public void visit(Object obj) {if(obj instanceof Rectangle) {/* do something */} else if(obj instanceof Circle) {/* do something */} else if(obj instanceof Triangle) {/* do something */}}}abstract class Shape {public abstract accept(ShapeVisitor visitor);}public abstract class ShapeVisitor {public void visit(Shape shape) {shape.accept(this);}public abstract void visitRectangle(Rectangle rect);public abstract void visitCircle(Circle circle);public abstract void visitTriangle(Triangle triangle);}class Rectangle extends Shape {public Point topLeft; // 改为了public。也可以用getter和setterpublic Point bottomRight;public Rectangle(Point topLeft, Point bottomRight) {this.topLeft = topLeft;this.bottomRight = bottomRight;}@Overridepublic void accept(ShapeVisitor visitor) {visitor.visitRectangle(this);}}class Circle extends Shape {/* more methods omitted */@Overridepublic void accept(ShapeVisitor visitor) {visitor.visitCircle(this);}}class Triangle extends Shape {/* more methods omitted */@Overridepublic void accept(ShapeVisitor visitor) {visitor.visitTriangle(this);}}class AreaVisitor extends ShapeVisitor {private double result; // 线程不安全public double calculateArea(Shape shape) {visit(shape);return result;}@Overridepublic void visitCircle(Circle circle) {result = Math.PI * circle.radius * circle.radius;}@Overridepublic void visitRectangle(Rectangle rect) {result = (rect.bottomRight.x - rect.topLeft.x)* (rect.bottomRight.y - rect.topLeft.y);}@Overridepublic void visitTriangle(Triangle tri) {result = 0.5 * Math.abs(tri.p1.x * tri.p2.y - tri.p2.x* tri.p1.y + tri.p2.x * tri.p3.y - tri.p3.x* tri.p2.y + tri.p3.x * tri.p1.y - tri.p1.x* tri.p3.y);}}class CenterVisitor extends ShapeVisitor {private Point result;public Point calculateArea(Shape shape) {visit(shape);return result;}@Overridepublic void visitCircle(Circle circle) {result = circle.center;}@Overridepublic void visitRectangle(Rectangle rect) {result = new Point((rect.bottomRight.x + rect.topLeft.x)/2.0,(rect.bottomRight.y + rect.topLeft.y)/2.0);}@Overridepublic void visitTriangle(Triangle tri) {result = new Point((tri.p1.x + tri.p2.x + tri.p3.x)/3.0,(tri.p1.y + tri.p2.y + tri.p3.y)/3.0);}}