製作なんてどうせ1人でやるから、Singletonなんて特に決めなくても、自分で覚えてるからいいや、と思ってました。
が、改めて、書籍:ActionScript3.0デザインパターンに書かれているSingletonの基本ソースを見て目からうろこが。。。
Singleton以外のところで感動したのでメモ。
今までのかなり無駄なことをしてたかも。
まずはSingletonクラスの基本ソース
package {
/**
* ...
* @author 393
*/
public class SingletonModel{
//自身をクラスメンバーとすることでどこからでもアクセスできるようにする。
private static var instance:SingletonModel;
//SingletonEnforcerを引数とすることで外からインスタンス化をできないように。
//※ただ、引数にnullを設定すれば外からでもインスタンス化できちゃうけど
public function SingletonModel(enforcer:SingletonEnforcer) {}
//このメソッドでSingletonModelのインスタンス(instance)の参照を取れる
public static function getInstance():SingletonModel{
//SingletonModel.instanceが生成されてなければ生成してから、
if (!SingletonModel.instance){
SingletonModel.instance = new SingletonModel(new SingletonEnforcer());
}
//returnでインスタンスを返す
return SingletonModel.instance;
}
}
}
class SingletonEnforcer {}
なにが目からうろこだったかって、自分自身をクラスメンバーとして保持するという方法。
これなら、どこのクラスからでも直接参照が取れるから、インスタンスの参照を持ちまわらなくてもいいのよね。
今までは、データモデルとなるようなクラスを、他のクラスに参照渡しても持ちまわってた。
これは一応上記書籍のMVCパターンを参考にしてたのだけど、MをSingletonにしちゃえば、VとかCをインスタンス化するときにわざわざ参照渡さなくてもいいじゃないのかな。
でも全部そうしちゃったらなんか落とし穴もありそうなきもするけど。
とりあえず、こんど使ってみる。
Tags: AS3, DesignPattern, Flash
カプセル化とは、
1.パブリックなプロパティは使わない
2.外部クラスのオブジェクトを参照しない。(そのクラスの引数を経由した参照は除く)
よくわからんけど、プロパティ値を変更するときは直接変更できないようにして(privateにする)、
パブリックなメソッドを用意してそれを使って内部のプロパティを変更するような仕組みを作るといいらしい。
2.については引数を使わずに外部クラスを参照する方法が浮かばないのだが。
Tags: AS3, DesignPattern, Flash
プログラムのタスク処理における一般的なやりかた。
他のオブジェクトへのアクセスを提供するためのクラス。
(他のオブジェクト:AS、img、xml、flv、FMS等)
最初にオブジェクトを全部作ってしまうのではなく、必要なときに作ろうという考え方。
仮想プロキシとリモートプロキシの2種類ある。
仮想プロキシ
Loaderクラスがまさにそれ。
プロキシという考え方があるから、画像を読み込みの際、読み込みが完了する前にLoaderのプロパティとか変更できるということらしい。
こんな感じか
//インスタンス生成
var loader:Loader = new Loader();
//loaderインスタンスにはまだ中身は無いけどプロパティとか設定しておく
loader.x = 100;
loader.y = 200;
loader.alpha = 0.5;
//表示リストに追加しちゃっておいても良い
this.addChild(loader);
//そして以下、欲しいときにload()メソッドを実行すればいい、みたいな感じ?
他に仮想プロキシの役割として、ゆるいシリアル化
ゆるいシリアル化の例(XMLの項目を
→硬いシリアル化:xmlを最初に全部要素、属性ごとに配列とかに割り振っちゃう
→ゆるいシリアル化:必要なときに応じて、都度xmlを取り出して使う
リモートプロキシ
対象がネットワーク先になるような感じ。
たとえばflikrAPIをたたいてAPIのメソッドに従った画像ひっぱってくるときの場合、みたいな
Tags: AS3, DesignPattern, Flash
シングルトンのルール
・(シングルトンインスタンスは)プライベートなstaticなプロパティに保持
・(シングルトンインスタンスに)アクセスするにはパブリックなメソッドを使う。(インスタンスが無い場合は生成)
汎用的なシングルトンパターン
package {
public class Singleton {
//Singletonインスタンスを保持
static private var _instance:Settings;
//他のオブジェクトからnew Singleton()では作らせないようにする
public function Singleton(enforcer:SingletonEnforcer) {
}
//インスタンス作成はこのメソッドで
public function getInstance():Settings {
//一回目はインスタンスを作る
if (Settings._instance == null){
Settings._instance = new Settings(new SingletonEnforcer));
}
//保持しているインスタンスを返す
return Settings._instance;
}
}
}
//new Singletonさせないためのクラス
class SingletonEnforcer{}
Tags: AS3, DesignPattern, Flash
アプリは、UI、ビジネスロジック、データモデルを持つ
→一般的なUIは、リスト、コンボボックス(クリック領域、スクロール領域)を持ち、
→ビジネスロジックは、入力にたいしてどのような処理、どんなデータモデルなのか知っている。
データとインターフェイスの分離に失敗すると
→オブジェクトを外部から利用しがたくなる(データを保持する形の入力フォームは駄目)
→UI変更が容易でなくなる(いろんな形のグラフ作成)
→同一データの多重同時参照が困難(表示携帯ごとにデータのコピー要)
→データの同期が困難(表示携帯ごとに処理わけが必要になる)
★モデル
ビューや、コントローラーから独立して存在できる格納庫。
→文字のような、プリミティブなデータを保持するが、複雑なデータ構造ももてる。
モデルはビューやコントローラーへの参照を持つことはない。
→モデルの柔軟性を保つという重要概念
★ビュー
UIサブシステムの視覚部分
→アニメーション、入力フォーム、チャート、ボタン、オーディオプレイヤーに不可欠なUI要素から構成
ポイント:視覚的な要素、モデルデータを読み取るロジック、UIの要求を処理する、これらで構成される
★コントローラー
入力処理を行う。
モデルやビューの更新もここで行う。
それぞれ(サブシステム)の関係性
モデルは他の要素の情報を持たないが、情報をブロードキャストはする
→ひとつのモデルは複数のビューから参照されることが可能
ビューはモデル情報を持ち、モデルから情報を受信し、モデル情報を読み取ることが可能
→モデルに何かを書き込むということはないが、すべてのビューはモデルへの参照を持つ
コントローラーもモデルにアクセス可能
→ユーザー入力、もしくはシステムイベントでモデルのデータを変更する役割を持つ
コントローラーとビューの関係は密接
ひとつのコントローラーが複数のビューを制御するのは一般的ではない
コントローラーとビューの関係性は1対1が望ましい
ただし、ASではコントローラーとビューをまとめてクラス化することが多い。(ドキュメントビュー実装)
モデルは独立したもので、ビューやコントローラーへの参照は持たない。
ビューはモデルデータの変更を描画に反映
Tags: AS3, DesignPattern, Flash
ポリモーフィズムとは、同一インターフェースを持つ、実装部分が微妙に異なるクラス。
時計でいったら、デジタル時計とアナログ時計における表示部分の実装。
Tags: AS3, DesignPattern, Flash
インターフェイスで定義するメソッドは、パブリックメソッドのみ
(修飾詞は指定できない。privateとか)
パブリックメソッドにはgetter/setterも含む。
インターフェイス
package {
public interface IPlus {
//myPlus関数定義
function myPlus(number1:Number , number2:Number):Number;
//ゲッターを定義
function get myNumber():Number;
//function set myNumber(value:Number):void;
}
}
クラス
//IPlusを実装したクラス
package {
public class Plus implements IPlus {
private var _myNumber:Number;
public function Plus() {
var num1:Number = 10;
var num2:Number = 5;
_myNumber = 10;
trace(myPlus(myNumber, num2));
}
//myPlus関数が無いとエラー
public function myPlus(num1:Number, num2:Number):Number{
return num1 + num2;
}
//get myNumber()ゲッターが無いとエラー
public function get myNumber():Number { return _myNumber; }
}
}
また継承することでもインターフェースも受け継がれる。(実装も継承される)
その際は抽象クラスという概念を持ったクラスを利用する。
抽象クラスはインスタンスを持てないクラスという意味。
ただしAS3では抽象クラスを管理するルールがないので自分で管理する。
Tags: AS3, DesignPattern, Flash
書籍:ActionScript3.0デザインパターンを読みながらのメモ(自分用)
1.分析フェーズ
→ユースケース作成(フォーマルユースケース)
→→主アクター、事前条件、基本経路、代替経路、特殊用件、検討事項
例)flickrAPIによる検索を使ったスライドショー
◆主アクター:
エンドユーザー
◆事前条件:
エンドユーザーは検索テキストボックス、送信、早送り、巻き戻しボタンの付いた画面を見ている
◆基本経路:
1.検索ワードを入力
2.送信ボタンをクリック
3.flickrがxmlを返す
4.xmlから画像を表示する
◆代替経路
3a.flickrAPIに接続できないときはエラーを表示
4a.検索結果でxmlが空っぽの場合は仮画像を表示
4b.画像の幅が規定サイズより小さい場合は拡大して表示
◆特殊要件
マウス操作以外にキーボードのみでの操作も可能とする
◆検討事項
ローディング処理方法
2.設計フェーズ
→CRCカード作成(Calss:クラス Responsibility:債務 Collaborator:コラボ)
→→クラスに債務を設定したら、当てはまるコラボ(当てはまるクラス)を設定
→クラス関係の精査:関連、集約、継承
→→関連:依存(uses)関係(MAPとMAPDATA)
→→集約:所有(has a)関係(MAPとSTREET)
→→継承:一般的な継承(is a)の概念→ポリモーフィズム
→パブリックAPIの書式を決める:債務のpublic,privateの割り振り
3.実装フェーズ
→コーディング規約の確認(俺流の設定)
→→ローカル変数名の先頭文字にはアンダースコア
→カプセル化:クラスをブラックボックス化するという考え方
→→パブリックなプロパティを使わない
→→→アクセサメソッドを使う
→→外部クラスのオブジェクトを直接参照しない
→→→そのクラスの引数を経由した参照は除く
→→→(駄目な使い方の例がないので、よくわからない p20)
→→配列などはコピーしたものを返すような設計が必要
→継承とコンポジション
→→継承は既知
→→→継承のメリット:利用が簡単
→→→継承のデメリット:サブクラスが良いカプセル化ではない、ひとクラスしか継承できない
→→コンポジション:元のクラスをバックエンドクラス、新しいクラスをフロントエンドクラス
→→→フロントエンドクラスはバックエンドクラスのインスタンスを利用する。
→→コンポジションのメリット:カプセル化が強い
→→コンポジションのデメリット:コーディングが増えて面倒
→→継承か、コンポジションかの判断の仕方
→→→A is BならAはBの継承とする
→→→A has B なら、AはBのコンポジションとする
Tags: AS3, DesignPattern, Flash
矢沢久雄の早わかりGoFデザインパターン(2) のAdapterの項をAS3で書いてみた。
こんなかんじでいいんだろうか?
Kyuuyoprog.as(ドキュメントクラス)
package {
import flash.display.Sprite;
/**
* ...
* @author 393
*/
public class KyuuyoProg extends Sprite {
public function KyuuyoProg() {
init();
}
private function init():void{
var shacho:Shacho = new Shacho(10000);
var shainAdapter:ShainAdapter = new ShainAdapter(shacho);
var shachokyuuyo:Number = getKyuuyo(shainAdapter);
var shain1:Shain = new Shain(90, 80);
var kyuuyo:Number = getKyuuyo(shain1);
trace( "shachokyuuyo : " + shachokyuuyo );
//出力:shachokyuuyo : 10000
trace( "kyuuyo : " + kyuuyo );
//出力:kyuuyo : 5670
}
private function getKyuuyo(obj:Shain):Number{
return obj.getJikan() * obj.getJikyu();
}
}
}
Shain.as
package {
/**
* ...
* @author 393
*/
public class Shain {
private var _jikyu:Number;
private var _jikan:Number;
public function Shain(jikyu:Number = 0, jikan:Number = 0) {
this._jikyu= jikyu;
this._jikan= jikan;
}
public function getJikan():Number {
//搾取
return _jikan - 10;
}
public function getJikyu():Number {
//搾取
return _jikyu * 0.9;
}
}
}
Shacho.as
package {
/**
* ...
* @author 393
*/
public class Shacho {
private var _koteikyu:Number;
public function Shacho(koteikyu:Number) {
_koteikyu = koteikyu
}
public function get koteikyu():Number { return _koteikyu; }
}
}
ShainAdapter.as(アダプタークラス)
package {
/**
* ...
* @author 393
*/
public class ShainAdapter extends Shain {
private var shachoObj:Shacho;
public function ShainAdapter(obj:Shacho) {
shachoObj = obj;
}
public override function getJikan():Number {
return 1;
}
public override function getJikyu():Number {
return shachoObj.koteikyu;
}
}
}
Tags: Adapter, AS3, DesignPattern, Flash