[AS3.0] 객체 생성 Singleton 패턴과 mx.core.Singleton

 Java 를 하다가 AS3을 하게 되면 private Constructor 를 사용하지 못한다는 사실에 꽤 당황스럽다.
( AS3은 현재 ECMA Script  표준에 맞춰진 언어이다. 다음 표준안에 나올듯.)
또 어떤 꽁수를 써야하는건지 ..

방법을 생각하다가 일단 찾아보니 참 많은 방법들이 존재했다.

http://koko8829.tistory.com/304 : 열이아빠님 블로그

 


첫번째 방법 내부 internal 클래스를 인자로 넘기기
http://blog.pixelbreaker.com/actionscript-3-0/as30-better-singletons 

package
{
	public class Singleton	{
		public static var instance:Singleton; 
		public static function getInstance():Singleton	{
			if( instance == null ) instance = new Singleton( new SingletonEnforcer() );
			return instance;
		}
 
		public function Singleton( pvt:SingletonEnforcer ){
			// init class
		}
	}
}
 
internal class SingletonEnforcer{}

소스의 internal class SingletonEnforcer{} 는 접근제한자가 internal 로 되어 있으므로 외부에서 접근을 할수 없다.



두번째 방법 임의의 Static 객체를 생성자로 받기
http://www.nulldesign.de/2007/11/20/as3-singletons-the-other-way/

package {
    public class Singleton {
        private static var instance:Singleton;
        private static const checker:Object = {};
 
        public function Singleton(initObj:Object) {
            if(initObj != checker) {
                throw new Error("Private constructor!");
            }
        }
 
        public static function getInstance():Singleton {
            if(instance == null) {
                instance = new Singleton(checker);
            }
            return instance;
        }
    }
}

private 으로 되어 있는 checker 객체를 매개변수로 받아야 하므로 이 역시 외부에서 접근을 할수 없다.



세번째 방법 Random 함수 사용하기.
http://berniesumption.com/software/private-constructors-for-actionscript/

class Singleton {
     private static var _instance:Singleton = null;
     // secret known only to this class
    private static const secret:Number = Math.random();
     /**
     * @private
     */
    public function Singleton(enforcer:Number) {
        if (enforcer != secret) {
            throw new Error("Error: use Singleton.instance instead");
        }
    }
     /**
     * Global single instance
     */
    public static function get instance():Singleton {
        if (_instance == null) {
            _instance = new Singleton(secret);
        }
        return _instance;
    }
}


세가지 방법 모두 아이디어가 참 좋은거 같다.
동일한 점은 클래스 내부에서만 접근 가능한 객체를 이용한다는 점이다.
꽁수인데 배울게 많다 ㅎ



mx.core.Singleton

Flex SDK 내부에서도 singleton 패턴을 사용할 것 같아서 찾아봤는데. 클래스 이름부터 Singleton이 있었다.
 하지만 이 클래스는 API문서에는 나오지 않고 내부적으로만 사용된다.
즉, 사용자가 직접 사용하는것은 권장하지 않는 것 같다.


제공되는 함수는 3개가 있다.

public static function registerClass(interfaceName:String, clazz:Class):void;


public static function getClass(interfaceName:String):Class;

public static function getInstance(interfaceName:String):Object;

SDK 소스를 보니 getInstance(interfaceName:String):Object 함수를 사용한 곳은 있지만만  registerClass(interfaceName:String, clazz:Class):void 함수를 사용한 곳은 찾을 수 없었다.

예를 들어 Singleton.getInstance()를 사용하고 있는  mx.managers.PopUpManager 를 살펴보면 get impl() 함수에서 Singleton.getInstance()  를 사용하는걸 알 수 있었는데 mx.managers.PopUpManager는  단순히 인터페이스와 비슷한 역활만 했다.

즉, 정리를 하자면 어딘가에서 IPopUpManage 인터페이스를 구현한 실체 클래스를  registerClass("mx.managers::IPopUpManager", 실체)  이런식으로 등록을 하고 mx.managers.PopUpManager 에서 IPopUpManager를 구현한 객체를 불러와서 사용하는것이다.

그러므로 이 패턴은 private Constructor 를 사용하지 못하므로 SDK에서 Singleton 패턴이 필요한 클래스들을 Singleton 으로 사용하기 위한 패턴으로 보인다.