« WWD | メイン | ActionScript 2.0でデザインパターン(Bridgeの巻き) »

ActionScript2.0でデザインパターン(AbstractFactoryの巻き)

蜜柑じゃなかった、未完です。

今回は、前回でふれた、クラスを文字列からロードするときに厳密に型を指定しないとだめ問題が解決してないため未完です。

抽象的な工場にて使用する抽象的な部品プログラムとその使い方の大まかな流れを決めて、具体的な仕事は具体的な工場と、具体的な部品プログラムに任せるパターンです。

これをやっとくと、具体的なプログラムに変更を加える必要があるとき、パッケージとその工場にあたるプログラムの名前を変更するだけでごっそり実装を差し替えることができて便利ですねと。なるほど。

ただ、同じ種類の処理に変更する時は、さくっと変更できるけど、処理の種類自体を追加したいときとかはいろいろ縛りが出て来ちゃうので注意。

以下ソース。

/**
###################################
 factory/Factory.as
 抽象的な工場。getFactoryメソッドのところが未完
 ###################################
 */
class factory.Factory {
	static function getFactory(classname:String){
		return new (eval(classname));
	}
	function createLink(caption:String,url:String){};
	function createTray(caption:String){};
	function createPage(title:String,author:String){};
}

/**
###################################
factory/Item.as
それぞれの部品を抽象化した部品
###################################
*/
class factory.Item {
private var caption:String;
function Item(cap:String){
caption = cap;
}
function makeHTML(){};
}

/**
###################################
factory/Link.as
個別のリンクを抽象化したもの。
###################################
*/
import factory.*;
class factory.Link extends Item{
var url:String;
function Link(cap:String, u:String){
super(cap);
url = u;
}
}

/**
###################################
factory/Tray.as
リンクをまとめる部品(トレイ)を抽象化したもの
###################################
*/
import factory.*;
class factory.Tray extends Item {
private var tray:Array;
function Tray(cap:String){
super(cap);
tray = new Array(); // コンストラクタでnewする必要がある。
}
function adding(item:Item){
tray.push(item);
}
}

/**
###################################
factory/Page.as
さらにそのトレイをまとめてページにする部品を抽象化
###################################
*/
import factory.*;
class factory.Page {
var title:String;
var author:String;
var content:Array = new Array();
function Page(t:String,a:String){
title = t;
author = a;
}
function adding(item:Item){
content.push(item);
}
function output():String{
var tmp = makeHTML();
return tmp;
}
function makeHTML():String{return "";};
}

/**
###################################
listfactory/ListFactory.as
具体的な工場。リンク作るクラスはこれ、
トレイ作るクラスはこれ、みたいに指定してる。
###################################
*/
import factory.*;
import listfactory.*;
class listfactory.ListFactory extends Factory{
function createLink(caption:String,url:String):Link{
return new ListLink(caption,url);
}
function createTray(caption:String){
return new ListTray(caption);
}
function createPage(title:String,author:String){
return new ListPage(title,author);
}
}

/**
###################################
listfactory/ListLink .as
具体的なリンク。
今回はリストで表現
###################################
*/
import factory.*;
class listfactory.ListLink extends Link{
function ListLink(cap:String,u:String){
super(cap,u);
}
function makeHTML():String{
return "<li><a href=¥'" + url +"¥'>"+ caption + "</a></li>¥n";
}
}

/**
###################################
listfactory/ListTray.as
具体的なトレイ。
<ul>で挟む。フラッシュのテキストエリアだと
うまく階層表示されないみたい。
IteratorはAS2.0にもあると思ってたんだけど、
コアクラスのフォルダみたら入ってなかったんで
自前で用意しました。for in やってもよかったんだけど、
せっかくIteratorパターン学んだんだし。
###################################
*/
import factory.*;
import factory.utils.*;
class listfactory.ListTray extends Tray {
function ListTray(cap:String) {
super(cap);
}
function makeHTML():String{
var tmp = new String();
tmp = "<li>¥n";
tmp = tmp + caption + "¥n";
tmp = tmp + "<ul>¥n";
var it:objectIterator = new objectIterator(tray);
while (it.hasNext()) {
var item= it.next();
trace("listTray+"+item.caption);
tmp = tmp + item.makeHTML();
}
tmp = tmp + "</ul>¥n";
tmp = tmp + "</li>¥n";
return tmp;
}
}

/**
###################################
listfactory/ListPage.as
具体的なページ。
また、Iterator出現。ページ、トレイ、リンクと入れ子
になってる。
###################################
*/
import factory.*;
import factory.utils.*;
class listfactory.ListPage extends Page{
private var title:String;
private var author:String;
function ListPage(tit:String,auth:String){
super(tit,auth);
title = tit;
author = auth;
}
function makeHTML():String{
var tmp = new String();
tmp = "<body>";
tmp = tmp + "<h1>"+ title + "</h1>¥n";
tmp = tmp + "<ul>¥n";

var it:objectIterator = new objectIterator(content);
while (it.hasNext()) {
var item = it.next();
tmp = tmp + item.makeHTML();
}
tmp = tmp + "</ul>";
tmp = tmp + "<br>author:"+author+"<br>";
tmp = tmp + "</body>";
return tmp;
}
}

/**
###################################
factory/utils/Iterator.as
先ほどのIteratorのインターフェースです。
###################################
*/
interface factory.utils.Iterator {
function hasNext():Boolean;
function next():Object;
}

/**
###################################
factory/utils/objectIterator .as
具体的にサーチするところ。
###################################
*/
import factory.utils.*;
class factory.utils.objectIterator implements Iterator{
private var _array:Array;
private var _cursor:Number;
function objectIterator(obj:Array) {
_array = obj;
_cursor = 0;
/*var prop:String;
for (prop in obj) {
_array.push(obj[prop]);
}*/
//オブジェクトをサーチするときはこっち
}
function hasNext():Boolean {
return (_cursor < _array.length);
}
function next():Object {
return _array[_cursor++];
}
}

/**
###################################
Main .as
や、やっと、メインが出て来た。
###################################
*/
import factory.*;
class Main {
function Main(path:MovieClip,classname:String){
var tmp = new String;
var fact:listfactory.ListFactory = Factory.getFactory(classname);
// ↑ここが型を指定しなきゃいけなくて動的にならない。
var asahi = fact.createLink("朝日新聞","http://www.asahi.com/");
var yomiuri = fact.createLink("読売新聞", "http://www.yomiuri.co.jp");
var us_yahoo = fact.createLink("Yahoo!","http://www.yahoo.com");
var jp_yahoo = fact.createLink("Yahoo!Japan","http://www.yahoo.co.jp");

var traynews = fact.createTray("新聞");
traynews.adding(asahi);
traynews.adding(yomiuri);

var trayYahoo = fact.createTray("Yahoo!");
trayYahoo.adding(us_yahoo);
trayYahoo.adding(jp_yahoo);

var page = fact.createPage("LinkPage", "佐藤魚");
page.adding(traynews);
page.adding(trayYahoo);
tmp = page.output();

// 表示
path.createTextField("tf", 1, 5, 5, 390, 490);
path.tf.border = true;
path.tf.multiline= true;
path.tf.wordWrap= true;
path.tf.html= true;
path.tf.htmlText = tmp;
}
static function main(){
var m = new Main(_root,"listfactory.ListFactory");
}
}

ぐわ。複雑だな。listfactoryパッケージ以下は今回はリストタグを出力するようになってますが、Tableにしたり、MovieClipにしたり、処理の構造が同じなら(リンクがあってそれをまとめてページを作ってって)簡単に差し替えできますね。

ということで、次回。
ちょっと今回は中途半端になっちゃったけど。

トラックバック

このエントリーのトラックバックURL:
http://www.minfish.jp/blog/mt-tb.cgi/29