пятница, 10 августа 2012 г.

Design pattern: Singleton

Привет!

С чего начинается разработка любого продукта? Точно! Как минимум, с проектирования. Один из шаблонов проектирования - это Singleton ( одиночка ).

В чем смысл этого шаблона? Допустим, у нас есть некий класс, и мы хотим иметь к нему доступ из любой части кода. Что-то типа статического класса.

Как это реализовать?

В принципе, можно просто наклепать кучу public static полей и методов, а можно вместо public static написать public и сделать public static ссылку на экземпляр класса.
На Википедии уже есть много реализаций на разных языках.

Где это можно использовать?
Я использую Одиночку при создании игр на Flash. Класс Main прекрасно подходит для реализации Singleton. Во-первых, он один. Во-вторых, я использую этот класс для связи всех остальных модулей игры.

Давайте потестим пример из Википедии.

Main подключаем как главный класс.
Main.as:
package
{ 
    import flash.display.MovieClip;
 
    public class Main extends MovieClip
    {
        public function Main () : void
        {
            Singleton.instance.sayHi();
        }
    }
}

Singleton.as:
package
{
    import flash.display.MovieClip;
 
    public class Singleton extends MovieClip
    {
        public static const instance: Singleton = new Singleton();
 
        public function Singleton ()
        {
            // Boolean(Singleton) is false when creating instance before static constructor executed.
            if(Singleton) throw new Error("Class is singleton.");
        }
  
        public function sayHi () : void
        {
            trace( "Hi!" );
        }
 
    }
}


Если в output написало "Hi!", то все сделано правильно. Но попробуем подключить Singleton.as, как главный класс.
Ошибка!

    >Error: Class is singleton. at Singleton()

Конечно, ведь главный класс создается при помощи оператора new, а нам не нужно этого делать, ведь уже есть константа instance с экземпляром класса. Значит нужно либо игнорировать эту ошибку, либо менять реализацию.

Ну, раз экземпляр создается, то надо это использовать!

Main.as как главный класс:
package
{
    import flash.display.MovieClip;
 
    public class Main extends MovieClip
    {
        public static var
        instance : Main;
 
        public function Main () : void
        {
            if ( !Main.instance )
            {
                Main.instance = this;
    
                // Do whatever you want here
                this.init();
            }
            else
            {
                trace( "This is an Singleton class." );
            }
        }
  
        private function init () : void
        {
            var foo : Foo = new Foo();
        }
 
        public function sayHi () : void
        {
           trace( "Hi!" );
        }
    }
}

Foo.as
package
{
    public class Foo
    {
        public function Foo ()
        {
            Main.instance.sayHi();
        }
    }
}


То есть, при создании экземпляра класса Main, в instance записывается созданный экземпляр.

Все, mission completed. :)

Комментариев нет:

Отправить комментарий