Поскольку этот вопрос был связан недавно, я бы тоже кое-что добавил. Мне было предложено использовать синглтон давным-давно, и я отказался от его использования, как только понял, как работают пространства имен и ссылки и что все, основанное на глобальных переменных, - плохая идея.
Aternative
Примечание это просто витрина, и я не советую вам использовать такой подход повсеместно.
Что касается альтернативы синглтону, вы могли бы иметь:
public class Global {
public static const myArray:Alternative = new Alternative();
}
и используйте его почти как синглтон:
var ga:Alternative = Global.myArray;
ga.e.addEventListener(GDataEvent.NEW_DATA, onNewData);
ga.e.addEventListener(GDataEvent.DATA_CHANGE, onDataChange);
ga.push(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "ten");
trace(ga[5]); // 5
И ваш Alternative.as будет выглядеть аналогично синглтону:
package adnss.projects.tchqs
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class Alternative extends Proxy
{
private var _data:Array = [];
private var _events:AltEventDisp = new AltEventDisp();
private var _dispatching:Boolean = false;
public var blockCircularChange:Boolean = true;
public function Alternative() {}
override flash_proxy function getProperty(id:*):* {var i:int = id;
return _data[i += (i < 0) ? _data.length : 0];
//return _data[id]; //version without anal item access - var i:int could be removed.
}
override flash_proxy function setProperty(id:*, value:*):void { var i:int = id;
if (_dispatching) { throw new Error("You cannot set data while DATA_CHANGE event is dipatching"); return; }
i += (i < 0) ? _data.length : 0;
if (i > 9 ) { throw new Error ("You can override only first 10 items without using push."); return;}
_data[i] = value;
if (blockCircularChange) _dispatching = true;
_events.dispatchEvent(new GDataEvent(GDataEvent.DATA_CHANGE, i));
_dispatching = false;
}
public function push(...rest) {
var c:uint = -_data.length + _data.push.apply(null, rest);
_events.dispatchEvent(new GDataEvent(GDataEvent.NEW_DATA, _data.length - c, c));
}
public function get length():uint { return _data.length; }
public function get e():AltEventDisp { return _events; }
public function toString():String { return String(_data); }
}
}
import flash.events.EventDispatcher;
/**
* Dispatched after data at existing index is replaced.
* @eventType adnss.projects.tchqs.GDataEvent
*/
[Event(name = "dataChange", type = "adnss.projects.tchqs.GDataEvent")]
/**
* Dispatched after new data is pushed intwo array.
* @eventType adnss.projects.tchqs.GDataEvent
*/
[Event(name = "newData", type = "adnss.projects.tchqs.GDataEvent")]
class AltEventDisp extends EventDispatcher { }
Единственное отличие формы Singleton заключается в том, что у вас может быть несколько экземпляров этого класса, поэтому вы можете использовать его следующим образом:
public class Global {
public static const myArray:Alternative = new Alternative();
public static const myArray2:Alternative = new Alternative();
}
чтобы иметь два отдельных глобальных массива или даже использовать их как переменную экземпляра одновременно.
Примечание
Обтекание массива подобным образом с использованием таких методов, как myArray.get(x)
или myArray[x]
, явно медленнее, чем доступ к необработанному массиву (см. Все дополнительные шаги, которые мы предпринимаем в setProperty
).
public static const staticArray:Array = [1,2,3];
С другой стороны, вы не можете это контролировать. И содержимое массива может быть изменено в любом месте.
Предупреждение о событиях
Я бы добавил, что если вы хотите, чтобы события обращались к данным таким образом, вы должны быть осторожны. Как и с каждым острым лезвием, его легко порезать.
Например, рассмотрим, что происходит, когда вы делаете это так:
private function onDataChange(e:GDataEvent):void {
trace("dataChanged at:", e.id, "to", Global.myArray[e.id]);
Global.myArray[e.id]++;
trace("new onDataChange is called before function exits");
}
Функция вызывается после изменения данных в массиве, и внутри этой функции вы меняете данные снова. В основном это похоже на что-то вроде этого:
function f(x:Number) {
f(++x);
}
Вы можете увидеть, что происходит в таком случае, если вы переключите myArray.blockCircularChange
. Иногда вы намеренно хотели бы иметь такую рекурсию, но вполне вероятно, что вы сделаете это «случайно». К сожалению, Flash внезапно остановит отправку таких событий, даже не объяснив, почему, и это может сбить с толку.
Скачать полный пример здесь
Почему использование глобальных переменных плохо в большинстве сценариев?
Я полагаю, что в интернете много информации об этом, но для полноты добавлю простой пример.
Представьте, что в вашем приложении есть какой-то вид, где вы отображаете текст, графику или, скорее всего, игровой контент. Скажем, у вас есть игра в шахматы. Возможно, вы разделили логику и графику на два класса, но вы хотите, чтобы оба работали на одних и тех же пешках. Таким образом, вы создаете переменную Global.pawns
и используете ее в классах Grahpics
и Logic
.
Все рэнди и работает без нареканий. Теперь вы пришли с прекрасной идеей - добавить опцию для пользователя, чтобы играть два матча одновременно или даже больше. Все, что вам нужно сделать, это создать еще один экземпляр вашего матча ... верно?
Что ж, вы обречены на этом этапе, потому что каждый экземпляр вашего класса будет использовать один и тот же массив Global.pawns
. Вы не только имеете эту глобальную переменную, но также ограничиваете себя в использовании только одного экземпляра каждого класса, который использует эту переменную: /
Поэтому, прежде чем использовать какие-либо глобальные переменные, просто подумайте дважды, действительно ли то, что вы хотите сохранить в нем, действительно глобально и универсально для всего вашего приложения.