[ActionScript 3.0] Singletonパターン

ActionScript 3.0ではコンストラクタをprivateにできないので、Singletonパターンを実装するには一工夫必要になる。

通常は該当クラスのインスタンスを保持するstaticな変数を用意しておくが、これだと間違ってクラス外でコンストラクタが実行されようとした際に、コンパイル時エラーではなく実行時エラーしか出ない。

	public class TestSimpleSingleton {
		
		private static var inside:Boolean;
		private static var _instance:TestSimpleSingleton;
		
		public function TestSimpleSingleton() {
			if (!inside) throw new Error("error"); // 実行時エラーのみ
		}
		
		public static function get instance():TestSimpleSingleton {
			if (!_instance) {
				inside = true;
				_instance = new TestSimpleSingleton;
				inside = false;
			}
			
			return _instance;
		}
		
	}

これを、一種の内部クラスを使うことによってコンパイル時エラーが出るようにする。

package  {
	public class TestMainSingleton {
		
		private static var _instance:TestMainSingleton;
		
		public function TestMainSingleton(inside:Inside) {
			
		}
		
		public static function get instance():TestMainSingleton {
			if (!_instance) _instance = new TestMainSingleton(new Inside);
			return _instance;
		}
	}

}

internal class Inside{}

ポイントは、packageの外に別のクラスを定義していること。バグ技でもなんでもなくActionScript 3.0の仕様で、同一ファイルではひとつのpackageとその内部のひとつのclassしか宣言できないが、packageの外側に記述された別のクラスはそのファイル内ならばアクセス可能というもの(有名なWonderflでも利用されている)。

ファイル外からはアクセス不可能なので、コンストラクタの引数に内部クラスのインスタンスを指定し、結果的にコンストラクタを外部から実行させないようにする。

内部クラスのアクセス修飾子をinternalにしているのは、単にこのファイルでしか利用できないことを明示化しているだけ。修飾子なしでもpublicでも問題ない。

なお、内部クラスの名称は外部ファイルに対しては非公開なため、好きな名前をつけていい。複数のSingletonクラス(のファイル)で重複してもなんら問題はない。

よって、以下のようなFlashDevelop用のテンプレートをつくることができる。

package $(Package) $(CSLB){
	
	/**
	$(CBI)* This Class is Singleton.
	$(CBI)* @author $(DefaultUser)
	$(CBI)*/
	public class $(FileName) $(CSLB){
		
		public function $(FileName)(b:Inside) $(CSLB){
			$(EntryPoint)
		}
		
		//---------------------------- for Singleton ----------------------------
		private static var _instance:$(FileName);
		public static function get instance():$(FileName) {
			if (!_instance) _instance = new $(FileName)(new Inside);
			return _instance;
		}
		//---------------------------- for Singleton ----------------------------
		
		
	}
	
}

internal class Inside{}

バージョン3でも4でも利用可能。ファイルの名前を「(好きな名前).as.fdt」にして、設定ファイルのあるディレクトリの「Templates\ProjectFiles\AS3Project」に入れておけば、ProjectManagerパネル(プロジェクト)のディレクトリを右クリックしたときに開かれるポップアップメニューの「新規作成」から、手軽にSingletonクラスを使えるようになる。

ここに自分が普段使っているファイルを置いておく。もしよかったら、利用してみてほしい。
SingletonClass.as