Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Синглтон в AS3 (http://www.flasher.ru/forum/showthread.php?t=214778)

ZergMaster 26.11.2017 17:14

Синглтон в AS3
 
у меня для этой задачи служит такой классик:

Код AS3:

package src.utils 
{
        import com.greensock.TweenLite;
        import flash.display.DisplayObjectContainer;
        import flash.display.InteractiveObject;
        import flash.display.Sprite;
        import flash.events.MouseEvent;
        import flash.text.TextField;
        import flash.text.TextFormat;
        import flash.utils.Dictionary;
        import flash.utils.clearTimeout;
        import flash.utils.setTimeout;
 
        public class BubbleText
        {
                private static const BUBBLE_COLOR:uint = 0xffffcc;
                private static const TIMER_TIME:uint = 700;
 
                private var _bubbleTimeout:uint;
 
                private static var _instance:BubbleText;
                private static var _stage:DisplayObjectContainer;
 
                private var _bubbleObjects:Dictionary = new Dictionary();
 
                private var _textDescription:TextField = new TextField();;
                private var _textSprite:Sprite = new Sprite();
 
                public function BubbleText(itIsSingleton:PrivateSingleton)
                {
                        _textSprite.addChild(_textDescription);
                }
 
                public static function gi():BubbleText
                {
                        if (!_instance)
                                _instance = new BubbleText(new PrivateSingleton());
 
                        return _instance;
                }
 
                public static function init(s:DisplayObjectContainer):void
                {
                        _stage = s;
                }
 
                public function registerObject(object:Sprite, description:String):void
                {
                        _bubbleObjects[object] = {target:object, description:description};
 
                        if (!_stage.hasEventListener(MouseEvent.MOUSE_OVER))
                        {
                                _stage.addEventListener(MouseEvent.MOUSE_OVER, mouseOverOutHandler, true);
                                _stage.addEventListener(MouseEvent.MOUSE_OUT, mouseOverOutHandler, true);
                        }
                }
 
                private function mouseOverOutHandler(event:MouseEvent):void
                {
                        var target:Sprite;
 
                        var check_mc:InteractiveObject = event.target as InteractiveObject;
                        while (check_mc != event.currentTarget as InteractiveObject)
                        {
                                var bubbleObject:Object = _bubbleObjects[check_mc as Sprite];
                                if (bubbleObject)
                                {
                                        target = bubbleObject.target;
                                        break;
                                }
 
                                check_mc = check_mc.parent;
                        }
 
                        if (!target) return;
 
                        switch(event.type)
                        {
                                case MouseEvent.MOUSE_OVER:
                                        target.addEventListener(MouseEvent.MOUSE_MOVE, mouseOverOutHandler);
                                        _bubbleTimeout = setTimeout(displayBubble, TIMER_TIME, target);
                                        break;
 
                                case MouseEvent.MOUSE_MOVE:
                                        removeBubble();
                                        _bubbleTimeout = setTimeout(displayBubble, TIMER_TIME, target);
                                        break;
 
                                case MouseEvent.MOUSE_OUT:
                                        removeBubble();
                                        target.removeEventListener(MouseEvent.MOUSE_MOVE, mouseOverOutHandler);
                                        break;
                        }
                }
 
                private function removeBubble():void
                {
                        clearTimeout(_bubbleTimeout);
 
                        _textSprite.graphics.clear();
                        _textDescription.text = '';
 
                        if(_stage.getChildByName(_textSprite.name))
                                _stage.removeChild(_textSprite);
                }
 
 
                private function displayBubble():void
                {       
                        var target:Sprite = arguments[0];
 
                        _textDescription.defaultTextFormat = new TextFormat('Verdana');
                        _textDescription.autoSize = TextFieldAutoSize.CENTER;
                        _textDescription.text = _bubbleObjects[target].description;
                        _textDescription.x = 0;
                        _textDescription.y = 0;
 
                        var gap:uint = 10;
                        _textSprite.graphics.lineStyle(0, 0, 1, true);
                        _textSprite.graphics.beginFill(BUBBLE_COLOR);
                        _textSprite.graphics.drawRoundRect(_textDescription.x-gap, _textDescription.y-gap, _textDescription.width+gap*2, _textDescription.height+gap*2, 10);
 
                        _textSprite.x = _stage.mouseX;
                        _textSprite.y = _stage.mouseY + 40;
 
                        if ((_textSprite.x + _textSprite.width) > _stage.stage.stageWidth)
                          _textSprite.x = _stage.mouseX - _textSprite.width + 30
 
                        if ((_textSprite.y + _textSprite.height) > _stage.stage.stageHeight)
                          _textSprite.y = _stage.mouseY - _textSprite.height// + 30
 
                        _stage.addChild(_textSprite);
                        _textSprite.alpha = 0;
 
                        TweenLite.to(_textSprite, 0.5, {alpha:1});
                }
        }
}
 
class PrivateSingleton
{
        public function PrivateSingleton() {}
}

класс, как можно увидеть, Singleton. Используется просто - сначала мы его инициализируем, передавая displayObjectContainer, в который будет добавлять всплывающее окошко. Это может быть stage, хотя я предпочитаю создавать отдельный слой в главной вьюхе. Второй шаг - это регистрация бабла на объекте, в которую передаем объект, над которым должен возникнуть бабл и текст, который будет отображаться. Вот собственно и все.

undefined 26.11.2017 17:31

а зачем PrivateSingleton нужен?

ZergMaster 26.11.2017 22:04

Синглтон в AS3
 
undefined
это реализация синглтона такая. Чтобы экземпляр можно было создать только изнутри класса (из функции gi()). Хотя да, есть возможность это обойти, добавив в тот же package класс с таким же именем... но это уже стараться надо.

caseyryan 27.11.2017 06:32

Цитата:

Хотя да, есть возможность это обойти, добавив в тот же package класс с таким же именем... но это уже стараться надо.
Ты пробовал так сделать?

А что мешает сделать синглтон вот так?
Код AS3:

package {
  public class Singletone {
 
      private static var _instance:Singleton = null;
 
      pubic function Singltone() {
          if (_instance) throw new Error("Singltone! Use Singltone.instance getter instead");
          _instance = this;
      }
 
      public static function get instance():Singltone {
          return _instance || new Singltone();
      }
  }
}

Зачем городить какие-то приватные ключи и другие конструкции?

ZergMaster 27.11.2017 08:55

caseyryan
ну, получается. что данная конструкция, которую ты предлагаешь, не защищает от создания конструктора из вне класса. Смысл то в этом.

undefined 27.11.2017 11:55

ZergMaster, общепринятая практика создания синглтонов - приватный конструктор и статический метод, который его дергает и возвращает инстанс.
В твоем коде назначение аргумента itIsSingleton в BubbleText совершенно не ясно т.к. он сам, судя по всему, является синглтоном(почему конструктор тогда public?) и еще зачем-то принимает синглтон на входе.Зачем?Почему?

ZergMaster 27.11.2017 12:15

Цитата:

Сообщение от undefined (Сообщение 1203149)
ZergMaster, общепринятая практика создания синглтонов - приватный конструктор и статический метод, который его его дергает и возвращает инстанс.

Все верно. Но приватным конструктор быть не может в as3. В данном же случае, если мы попытаемся создать экземпляр BubbleText откуда-то извне, кроме как из статического метода gi(), то у нас ничего не получится, так как туда нужно будет передать PrivateSingleton, который находится внутри документкласса BubbleText. PrivateSingleton видно только внутри документкласса BubbleText, поэтому при создании экземпляра из функции gi() проблем не будет.
А название такое, чтобы если вдруг я бы попытался создать экземпляр BubbleText где-нибудь в коде, я бы увидел, что ему нужно передать некий PrivateSingleton. Я согласен, что название, быть может, не самое удачное. Лучше назвать PrivateFromSingleton. Само же название параметра "itIsSingleton" как бы намекает, что мы имеем дело с данным паттерном и не нужно создавать его экземпляр, а искать статический метод gi()

Добавлено через 4 минуты
вот в java возможно создать приватный конструктор и поэтому там таких извращений не требуется...

caseyryan 27.11.2017 15:58

Цитата:

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

вот в java возможно создать приватный конструктор и поэтому там таких извращений не требуется...
Джава сама - одно сплошное извращение)

ZergMaster 27.11.2017 16:39

Цитата:

Сообщение от caseyryan (Сообщение 1203153)
в любом случае экземпляр будет только один, что через instance, что просто вызовом конструктора в первый раз

это да. Не нравится мне так, непорядок. Я не гонюсь за коротким кодом с некоторых пор... ) А вот аккуратненько все должно быть и по полочкам - это желательно по возможности.
Если уж на то пошло, тогда мне больше нравится такой вариант:

Код AS3:

package {
 
        public class MySingleton {
 
                private static var _instance:MySingleton;
                //Переменная доступа
                private static var _isConstructing:Boolean;
 
                public function MySingleton() {
                        if (!_isConstructing) throw new Error("Singleton, use MySingleton.instance");
                }
 
                public static function get instance():MySingleton {
                        if (_instance == null)  {
                                _isConstructing = true;
                                _instance = new MySingleton();
                                _isConstructing = false;
                        }
                        return _instance;
                }
        }
}

Хоть, как завещал дедушка Мартин, это и не тру, конечно, пользоваться флагами, но зато тут не создать, опять же, экземпляр из вне.

Цитата:

Сообщение от caseyryan (Сообщение 1203153)
Джава сама - одно сплошное извращение)

А что такое? Детская травма?)

undefined 27.11.2017 16:53

Код AS3:

_isConstructing = true;
_instance = new MySingleton();
_isConstructing = false;

Это что защита для многопоточности? :)


Часовой пояс GMT +4, время: 06:06.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.