このブログは、自分のFlash等々のスキルアップのために始めました。で、自分のスキルってどれくらいなのかなと思ったとき、端的にって今一歩のところで上級に届かないって所なのかなと思う。
例えば、だいたい最初に考えた仕様通りにコーディングできてとりあえず動くものは作れるのだけど、抽象クラスとかってなんなの?なんで使うのかいまいちピンとこないって感じです。そんなこんななんで、デザインパターンを入門してみます。
よくいわれる人種ネタで、「ドイツ人は歩く前に考え、イギリス人は歩きながら考え、イタリア人は歩いてから考える」というのがあります。(実際にはそうでもないような気がするけど)昔イギリスに留学してたというのもあってか(これも関係ないかもしれないけど)イギリス・スタイルがしっくりくる感じ。
本でじっくり学んでから行動を起こすより、なにかをしながら足りないところは本を読む。今関係ないところはあとで読むみたいなスタイル。すなわちこのブログみたいなスタイル。
何はともあれ、とりあえず手を動かしてみます。
使用するテキストは
「増補改訂版Java言語で学ぶデザインパターン入門」結城 浩
同僚のひろしさんお勧めの本です。これをパラパラめくって必要ありそうなところをjavaからAS2.0に書き換えていろいろ学んでしまおうというのがこのコーナーの趣旨。一回目は「Iterator(1つ1つ数え上げる)」です。
で実際に書いたコードがこれ。全部で6本。
・IteratorMain.as
・Book.as
・Iterator.as
・Aggregate.as
・BookShelf.as
・BookShelfIterator.as
以下がそのコードとコメントアウト
//IteratorMain.as class IteratorMain{ // メインクラスfunction IteratorMain(path :MovieClip , txt:String) {
var bookshelf = new BookShelf(4);
//BookShelfに4個アイテムを追加します。
bookshelf.appendBook(new Book("Around the World in 80 Days"));
bookshelf.appendBook(new Book("Bible"));
bookshelf.appendBook(new Book("Cinderella"));
bookshelf.appendBook(new Book("Daddy-long-leg"));
var it = bookshelf.iterator();var tmp:String = "";
// 一個ずつサーチして名前をとってきてtmpに入れる。
while(it.hasNext()) {
tmp = tmp + it.next().getName()+"¥n";
}
// どのようなサーチの実装をとっても
// 上のコードですますことができて便利。
// 表示
path.createTextField("tf", 1, 5, 5, 190, 190);
path.tf.border = true;
path.tf.multiline= true;
path.tf.wordWrap= true;
path.tf.text = tmp;
}static function main() {
var t :IteratorMain= new IteratorMain(_root);
}
}
// Book.as class Book{ // 個別のアイテムのクラス。名前を保持してかえすだけ。 private var name:String; function Book(n:String){ name = n; } function getName():String{ return name; } }
// Iterator.as interface Iterator{ // インターフェース。実装はBookShelfIterator.as function hasNext():Boolean; function next():Object; }
// Aggregate.as interface Aggregate{ // インターフェース。 function iterator():Iterator; }
// BookShelf.as class BookShelf implements Aggregate{ // AggregateインターフェースのIteratorメソッドの実体が書かれているクラスprivate var books:Array;
private var last:Number;
function BookShelf(maxsize:Number){
last = 0;
books = new Array(maxsize);
// Bookたちをしまう配列を作る
}
function getBookAt(index:Number):Book{
return books[index];
}
function appendBook(book:Book):Void{
books[last] = book;
last++;
}
function getLength():Number{
return last;
}
function iterator():Iterator{
// これが実体。BookShelfをサーチするためのBookShelfIterator
// のインスタンスを返す。
return new BookShelfIterator (this);
}
}
// BookShelfIterator.as class BookShelfIterator implements Iterator{ // BookShelf内のBookをサーチする機能を実装するクラスprivate var bookShelf:BookShelf;
private var index:Number;
function BookShelfIterator (bs:BookShelf){
bookShelf = bs;
index = 0;
}
function hasNext():Boolean{
// 現在指しているインデックスが最終かどうか判別
if (index < bookShelf.getLength() ) {
return true;
} else {
return false;
}
}
function next():Object{
// インデックスを一つ進め相当するBookを返す
var book:Book =bookShelf.getBookAt(index);
index++;
return book;
}
}
mtascで
mtasc -swf iterator.swf -main IteratorMainas.as -header 200:200:30
みたいにコンパイルすると動きます。とりあえず実際に書いてみてIteratorパターンの勘所みたいなところはわかりました。メインの関数のwhileをまわしてるところですね。実体の部分を別のクラスに書くことでそれぞれのクラスの依存関係を弱めようってところですか。Flash OOP本にも書いてあったけど、サーチするものが変わったりその方法が変わったりの変更にも耐えられるというところ。確かにこれは便利かも。
でもやっぱりここでIterator.asとAggregate.asのインターフェースを用意する意味がよく分かんなかった。なーんか面倒になるだけじゃん。うーむ。プログラムの規模や複雑さにもよるのかな。
参考テキストにも書いてあった通り読み進めていけばそこらへんも理解できるらしい。
※えーと、一応このコーナーははてなのnaoya氏のこのエントリーにインスパイアされて始めました。池田君元気ですか?
ということで次回へ続く。