JAVAC.JP
HOSHI TETSUYA 星鉄矢
2005/07/26
hossy@javac.jp
http://www.javac.jp
Google
WWW を検索 WWW.JAVAC.JP を検索

C-1 interfaceとmixinでDataStorageを構築する

現在のDataStorageに対し、何となく納得がいかなかったので、修正してみようと考える。
(何が納得いかないのかは、(2-3)回転処理を行うためにrotateメソッド群を加えるを参照)

方法としては、インターフェイス(interface)としてPointDataStorage,LineDataStorageを形成し、それらを継承(implements)したModelDataStorageに対して、RotateMixerでミックスインを行おうというものだ。この方法では、PointDataStorageというinterfaceを継承しているクラスに対してミックスインを行うので、セッター・ゲッターが存在しないということはない。

以下がソースである。
PointDataStorage.as
---
interface PointDataStorage{
    public function getPointListLength():Number;
    public function addPoint(id:String,x:Number,y:Number,z:Number,
    note:String,comment:String):Void;
    public function setPointPosition(index:Number,x:Number,y:Number,z:Number):Void;
    public function getPointId(index:Number):String;
    public function getPointPosX(index:Number):Number;
    public function getPointPosY(index:Number):Number;
    public function getPointPosZ(index:Number):Number;
    public function getPointNote(index:Number):String;
    public function getPointComment(index:Number):String;
}
---

LineDataStorage.as
---
interface LineDataStorage{
    public function getLineListLength():Number;
    public function addLine(id:String,point1:String,point2:String,
    note:String,comment:String):Void;
    public function getLinePoint1(index:Number):String;
    public function getLinePoint2(index:Number):String;
    public function getLineNote(index:Number):String;
    public function getLineComment(index:Number):String;
}
---

RotateMixer
---
class RotateMixer{
    function RotateMixer(){
    }

    public function addRotateX(ref:Object):Void{
        ref.rotateX=function(theta:Number){
            var len:Number=this.getPointListLength();
            for(var i:Number=0;i<len;i++){
                var old_x:Number=this.getPointPosX(i);
                var old_y:Number=this.getPointPosY(i);
                var old_z:Number=this.getPointPosZ(i);
                var new_x:Number=old_x;
                var new_y:Number=old_y*Math.cos(theta)+old_z*Math.sin(theta);
                var new_z:Number=-old_y*Math.sin(theta)+old_z*Math.cos(theta);
                this.setPointPosition(i,new_x,new_y,new_z);
            }
        };
    }

    public function addRotateY(ref:Object):Void{
        ref.rotateY=function(theta:Number){
            var len:Number=this.getPointListLength();
            for(var i:Number=0;i<len;i++){
                var old_x:Number=this.getPointPosX(i);
                var old_y:Number=this.getPointPosY(i);
                var old_z:Number=this.getPointPosZ(i);
                var new_x:Number=old_x*Math.cos(theta)-old_z*Math.sin(theta);
                var new_y:Number=old_y;
                var new_z:Number=old_x*Math.sin(theta)+old_z*Math.cos(theta);
                this.setPointPosition(i,new_x,new_y,new_z);
            }
        };
    }

    public function addRotateZ(ref:Object):Void{
        ref.rotateZ=function(theta:Number){
            var len:Number=this.getPointListLength();
            for(var i:Number=0;i<len;i++){
                var old_x:Number=this.getPointPosX(i);
                var old_y:Number=this.getPointPosY(i);
                var old_z:Number=this.getPointPosZ(i);
                var new_x:Number=old_x*Math.cos(theta)+old_y*Math.sin(theta);
                var new_y:Number=-old_x*Math.sin(theta)+old_y*Math.cos(theta);
                var new_z:Number=old_z;
                this.setPointPosition(i,new_x,new_y,new_z);
            }
        };
    }

    public function addGetGravityX(ref:Object):Void{
        ref.getGravityX=function():Number{
            var len:Number=this.getPointListLength();
            var ret:Number=0;
            for(var i:Number=0;i<len;i++){
                ret+=this.getPointPosX(i);
            }
            return ret/len;
        };
    }

    public function addGetGravityY(ref:Object):Void{
        ref.getGravityY=function():Number{
            var len:Number=this.getPointListLength();
            var ret:Number=0;
            for(var i:Number=0;i<len;i++){
                ret+=this.getPointPosY(i);
            }
            return ret/len;
        };
    }

    public function addGetGravityZ(ref:Object):Void{
        ref.getGravityZ=function():Number{
            var len:Number=this.getPointListLength();
            var ret:Number=0;
            for(var i:Number=0;i<len;i++){
                ret+=this.getPointPosZ(i);
            }
            return ret/len;
        };
    }

    public function addCentering(ref:Object):Void{
        ref.centering=function():Void{
            var len:Number=this.getPointListLength();
            var cx:Number=this.getGravityX();
            var cy:Number=this.getGravityY();
            var cz:Number=this.getGravityZ();
            for(var i:Number=0;i<len;i++){
                var x:Number=this.getPointPosX(i);
                var y:Number=this.getPointPosY(i);
                var z:Number=this.getPointPosZ(i);
                x-=cx;
                y-=cy;
                z-=cz;
                this.setPointPosition(x,y,z);
            }
        };
    }
}
---

ModelDataStorage.as
---
class ModelDataStorage implements PointDataStorage,LineDataStorage{
    private var mixer:RotateMixer;
    private var pointList:Array;
    private var lineList:Array;
    public var rotateX:Function;
    public var rotateY:Function;
    public var rotateZ:Function;
    private var getGravityX:Function;
    private var getGravityY:Function;
    private var getGravityZ:Function;

    function ModelDataStorage(){
        mixer=new RotateMixer();
        mixer.addRotateX(this);
        mixer.addRotateY(this);
        mixer.addRotateZ(this);
        mixer.addGetGravityX(this);
        mixer.addGetGravityY(this);
        mixer.addGetGravityZ(this);
        mixer.addCentering(this);
        reset();
    }

    public function reset():Void{
        pointList=new Array();
        lineList=new Array();
    }

    public function getPointListLength():Number{
        return pointList.length;
    }

    public function getLineListLength():Number{
        return lineList.length;
    }

    public function addPoint(id:String,x:Number,y:Number,z:Number,
    note:String,comment:String):Void{
        var o:Object=new Object();
        o.id=id;
        o.x=x;
        o.y=y;
        o.z=z;
        o.note=note;
        o.comment=comment;
        pointList.push(o);
    }

    public function setPointPosition(index:Number,x:Number,y:Number,z:Number):Void{
        pointList[index].x=x;
        pointList[index].y=y;
        pointList[index].z=z;
    }

    public function getPointId(index:Number):String{
        return String(pointList[index].id);
    }

    public function getPointPosX(index:Number):Number{
        return Number(pointList[index].x);
    }

    public function getPointPosY(index:Number):Number{
        return Number(pointList[index].y);
    }

    public function getPointPosZ(index:Number):Number{
        return Number(pointList[index].z);
    }

    public function getPointNote(index:Number):String{
        return String(pointList[index].note);
    }

    public function getPointComment(index:Number):String{
        return String(pointList[index].comment);
    }

    public function addLine(id:String,point1:String,point2:String,
    note:String,comment:String):Void{
        var o:Object=new Object();
        o.id=id;
        o.point1=point1;
        o.point2=point2;
        o.note=note;
        o.comment=comment;
        lineList.push(o);
    }

    public function getLineIndex1(index:Number):Number{
        return Number(lineList[index].index1);
    }

    public function getLineIndex2(index:Number):Number{
        return Number(lineList[index].index2);
    }

    public function getLineId(index:Number):String{
        return String(lineList[index].id);
    }

    public function getLinePoint1(index:Number):String{
        return String(lineList[index].point1);
    }

    public function getLinePoint2(index:Number):String{
        return String(lineList[index].point2);
    }

    public function getLineNote(index:Number):String{
        return String(lineList[index].note);
    }

    public function getLineComment(index:Number):String{
        return String(lineList[index].comment);
    }

    public function addPointIndexToLineLists():Void{
        var len:Number=getLineListLength();
        for(var i:Number=0;i<len;i++){
            addPointIndexToLine(i);
        }
    }

    private function addPointIndexToLine(index:Number):Void{
        var point1:String=getLinePoint1(index);
        var point2:String=getLinePoint2(index);
        var pointIndex1:Number=getPointIndexFromId(point1);
        var pointIndex2:Number=getPointIndexFromId(point2);
        lineList[index].index1=pointIndex1;
        lineList[index].index2=pointIndex2;
    }

    private function getPointIndexFromId(id:String):Number{
        var ret:Number;
        for(var i:Number=0;i<pointList.length;i++){
            var targetId:String=getLineId(i);
            if(id==targetId){
                ret=i;
                break;
            }
        }
        return ret;
    }
}
それはそうと、そろそろDataStorageの雛形を作って置きたいと思う、今日この頃である。

また、デザインパターンをよく調べたところ、Tmplate Method パターンというデザインパターンがあるので、もしかすると、前出の「セッター・ゲッターを抽象化メソッドにして処理を行う」という手法は、これに相当するのかもしれず、そう考えると、前出のままでも問題ないのかもしれない。



BACKTOPNEXT




All Contents Copyright (C) 2005 HOSHI Tetsuya
Home