Flex SDK のソースで見る Singleton パターン

2011.07.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

毎度お世話になっております。クラスメソッドの稲毛です。

今回は Flex SDK のソースの中に見られる Singleton パターンについて書こうと思います。

Java のようにコンストラクタを private として宣言できない ActionScript 3 ですが、これまで「フラグを用いる」「内部クラスを用いる」などの手法で、シングルトン(new によるインスタンス生成の抑止)を実現する方法が編み出されてきました。そんな中で「mx.resources.ResourceManager」などのシングルトンクラスはどのように実装されているのかと興味が湧いたので調べてみた所、下記のようなことが分かりました。

  • 2つのクラスと1つのインタフェースで構成される。
    • インスタンスを提供するクラスメソッドを持つ「シングルトンクラス(例.mx.resources.ResourceManager)」
    • 提供するインスタンスの実装を持つ「実装クラス(例.mx.resources.ResourceManagerImpl)」
    • 提供するインスタンスの「インタフェース(例.mx.resources.IResourceManager)」
  • 「実装クラス」はメタデータタグ「ExcludeClass」の宣言により、コード補完の候補として現れない。
  • 「実装クラス」が「インタフェース」を実装する。(「シングルトンクラス」が実装するのではない。)

以下に簡単な実装例を記します。

Singleton.as(シングルトンクラス)

package
{
public class Singleton
{
    private static var instance:ISingleton;
    
    public static function getInstance():ISingleton
    {
        if (!instance)
        {
            instance = new SingletonImpl();
        }
        return instance;
    }
    
    public function Singleton()
    {
        super();
    }
}
}

「instance」が自身のインスタンスではない所が一般的なSingletonパターンとは異なる点です。

ISingleton.as(インタフェース)

package
{
public interface ISingleton
{
    function method():void;
}
}

実装クラスのメソッドを公開する為のインタフェースです。

SingletonImpl.as(実装クラス)

package
{
[ExcludeClass]
public class SingletonImpl implements ISingleton
{
    public function SingletonImpl()
    {
        super();
    }
    
    public function method():void
    {
        // Do something.
    }
}
}

開発者によってインスタンス化されないようにメタデータタグ「ExcludeClass」が指定されています。FlashBuilder のコード補完などからは隠蔽されるので、開発者へ公開する為に前述のインタフェースが必要となります。

単一クラスで実現できない為に幾分か手間となってしまいますが、個々のクラスを見ると内部クラスやフラグを必要としない分、シンプルで見通しが良くなっているのではないかと思います。Singleton パターン実現の選択肢のひとつとして頭の片隅に置いておくと良いのではないかと思います。

なお、Flex Framework 内では「mx.core.Singleton」という非公開のクラスを用いてシングルトンクラスが管理されています。「mx.core.Singleton」が持つクラスメソッド「registerClass(interfaceName:String, clazz:Class):void」を用いて、インタフェース名(例."mx.core.IPopupManager")に対するクラスの参照を登録し直すことでフレームワーク標準のマネージャクラスの実装を上書きすることが可能です。

詳しくは Adobe Developer Connection の Cookbooks に掲載(Overriding framework default implementations for mx.managers classes)されています。