— boreal-kiss.com

[DesignPatterns]疑似privateコンストラクタで勇者を唯一作成

Design PatternsのSingletonパターンついてのメモ。例えば以下のような勇者クラス(Yusha.as)を作成したとする。

package singleton{
    public class Yusha{
        public function sayHello():void{
            trace("僕が勇者だ");
        }
    }
}

RPGにおいて勇者は一般に物語中に一人しか存在しない。従って以下のように複数勇者が作成できるアプリケーション(Main.as)はRPG的に問題がある。

package {
    import flash.display.Sprite;
    import singleton.Yusha;

    public class Main extends Sprite{
        public function Main(){
            var y1:Yusha = new Yusha();
            var y2:Yusha = new Yusha();
            var y3:Yusha = new Yusha();

            y1.sayHello();//僕が勇者だ
            y2.sayHello();//僕が勇者だ
            y3.sayHello();//僕が勇者だ
        }
    }
}

そこでSingletonパターンを利用する。例えばCreating Mashups with Adobe Flex and AIRでは以下のような方法でインスタンスを唯一作成する方法が紹介されている。

package singleton{
    public class Yusha{
        
        private static var _instance:Yusha;
        
        public static function getInstance():Yusha{
            if (Yusha._instance == null){
                Yusha._instance = new Yusha();
            }
            return Yusha._instance;
        }
    }
}

この方法だとgetInstance()メソッドを使う限り勇者は複数作成されないが、以下のように直接Yushaクラスを作成された時に対処できなくなる。

//In Main.as
var y:Yusha = new Yusha();

Yushaクラスのコンストラクタをprivateにできれば一件落着だけど、ActionScript 3.0ではコンストラクタをprivateにできない。そこで同パッケージ内にDummyクラスを用意、それをYushaクラスの引数としてYushaクラスのコンストラクタにパッケージ外部からアクセスできないようにする(疑似private化)。

//Yusha.as
package singleton{
    public class Yusha{
        
        private static var _instance:Yusha;
        
        public function Yusha(d:Dummy){   
        }
        
        public static function getInstance():Yusha{
            if (Yusha._instance == null){
                Yusha._instance = new Yusha(new Dummy());
            }
            return Yusha._instance;
        }
        
        public function sayHello():void{
            trace("僕が勇者だ");
        }
    }
}
//Dummy.as
package singleton{
    internal class Dummy{
    }
}

これによりYushaクラスは作成時にDummyクラスを引数とし、さらにDummyクラスはsingletonパッケージ外部からアクセス不能なので、MainクラスからのYushaクラスの呼び出しはgetInstance()メソッドからのみ可能となる。

//In Main.as
var y1:Yusha = new Yusha();//Error
var y2:Yusha = new Yusha(new Dummy());//Error
var y3:Yusha = Yusha.getInstance();//OK

これにより勇者は唯一無二作成されることになりました。めでたしめでたし。

[関連記事]
Tanablog: 複数版 Singleton パターン

ActionScript 3.0 Design Patterns (Adobe Developer Library)

追記:2008/07/11

Dummyクラスはsingletonパッケージ内であればアクセス可能なので、記事タイトルの「疑似private」は「疑似internal」とした方が良いかもしれない。AS3で1ファイルに複数のクラスを定義する方法 – てっく煮ブログのように、DummyクラスをYushaクラスファイル内部に定義することで、Dummyクラスへのアクセスをprivate化することもできる。

0 comments
Submit comment