[2023] Re:『Java謎+落とし穴徹底解明』の正誤について
    
    投稿者:藤四郎
    2017/11/16 19:37:20
    
    
    詳しく解説くださり、ありがとうございます。 adjustBoundary() に引数をわ
たすとなると、ワールド座標系版とデバイス座標系版にわけるのがすじという
ようなはなしになってしまうので、引数なしの adjustBoundary() を採用され
たというわけですね。疑問がすっきり解消しました。
さて、 p. 228 「別の方法」について、そもそも Abstract Factory パターン
をよくわかってないのでとんだ見当はずれだったらもうしわけありませんが、
「各 Shape のオブジェクトに……くっつける」ときに使い、「いざ描画すると
きには…… DrawShapeRuntime にダウンキャスト」するとなると、
abstract class AbstractFactory {
    abstract PolylineRuntime createPolylineRuntime(Polyline polyline);
    abstract CircleRuntime createCircleRuntime(Circle circle);
    abstract RectangleRuntime createRectangleRuntime(Rectangle rectangle);
}
class DrawFactory extends AbstractFactory {
    PolylineRuntime createPolylineRuntime(Polyline polyline) {
        return new DrawPolylineRuntime(polyline);
    }
    // ...
}
としか思いつけませんでした。しかし、こうだと Visitor 同様「 if else を
ずらずら」になるように思います。また、各 Shape のコンストラクターに
AbstractFactory の分の引数を追加することになるのでしょうか。
ちなみに、つぎのようにするのではだめでしょうか。
abstract class Shape {
    ShapeRuntime shapeRuntime;
}
abstract class ShapeRuntime {
    protected DrawShapeRuntime drawShapeRuntime;
    
    abstract DrawShapeRuntime getDrawShapeRuntime();
}
class PolylineRuntime extends ShapeRuntime {
    
    PolylineRuntime(Polyline polyline) {
        this.drawShapeRuntime = new DrawPolylineRuntime(polyline);
    }
    DrawShapeRuntime getDrawShapeRuntime() {
        return this.drawShapeRuntime;
    }
}
interface DrawShapeRuntime {
    void draw(Drawable d);
}
class DrawPolylineRuntime implements DrawShapeRuntime {	 // 「 PolylineRuntime を継承」無用
    private Polyline polyline;
    
    DrawPolylineRuntime(Polyline polyline) {
        this.polyline = polyline;
    }
    
    public void draw(Drawable d) {
        Point2D[] points = this.polyline.getPoints();
        for (int i = 0; i < points.length - 1; i++) {
            d.drawLine(points[i].getX(), points[i].getY(),
                       points[i+1].getX(), points[i+1].getY());
        }
    }
}
class Polyline extends Shape {
    private Point2D[] points;
    public Polyline(Point2D[] points) {
        this.points = points;
        this.shapeRuntime = new PolylineRuntime(this);
    }
    
    public Point2D[] getPoints() {
        return this.points;
    }
}
// Circle, Rectangle の対応分は略
/*
XDrawCanvas の paint() の
	shape.draw(this.drawWindow);
を
	shape.shapeRuntime.getDrawShapeRuntime().draw(this.drawWindow);	// 「DrawShapeRuntime にダウンキャスト」不要
に変更。
*/