Я решил пойти по третьему пути: создать коллекцию методов и брать методы из нее.
Это быстрый вариант, понятный большинству разработчиков и в нем можно задействовать константы класса FormatSVG. Хотя без некоторых переделок не обойтись.
Опять протестируем на коротком примере.
Объявим статической константой коллекцию методов и добавим ссылку на метод:
Код AS3:
private static const DRAW_METHODS:Object = new Object();
DRAW_METHODS[FormatSVG.MOVE_TO_ABSOLUTE] = createMoveToCommand;
Тестируем и обнаруживаем, что статическая константа не видит метод экземпляра класса. Ну, в общем это правильно, особенно учитывая то, что каждый метод привязан к экземпляру класса.
Мы можем создать такой экземпляр перед объявлением коллекции:
Код AS3:
private static const INSTANCE:PathToArray = new PathToArray(null, null);
Тестируем, получаем ошибку. Причина ошибки понятна: мы передали невалидные аргументы. Чтобы от нее избавиться, достаточно в конструктор класса добавить проверку:
Код AS3:
if (svgNode == null || dCmds == null) {
return;
}
Теперь добавляем тестовый вызов:
Код AS3:
case FormatSVG.MOVE_TO_ABSOLUTE :
var drawMethod:Function = DRAW_METHODS[FormatSVG.MOVE_TO_ABSOLUTE];
trace("drawMethod: " +drawMethod);
j = drawMethod.call(this, svgCmds, j);
// j = createMoveToCommand(svgCmds, j);
break;
и опять обламываемся. Функция в коллекции найдена, но внутри функции всё равно идет обращение к экземплярам пустого объекта.
Чтобы избежать этого, передадим текущий объект в аргументах и внутри методов будем использовать обращение используя только его. А поскольку пустой экземпляр в таком случае не нужен, удаляем объявление константы INSTANCE и делаем метод createMoveToCommand статическим.
Вот что получается:
Код AS3:
private static const DRAW_METHODS:Object = new Object();
DRAW_METHODS[FormatSVG.MOVE_TO_ABSOLUTE] = createMoveToCommand;
private function makeDrawCmds(svgCmds:Array):void {
....
case FormatSVG.MOVE_TO_ABSOLUTE :
var drawMethod:Function = DRAW_METHODS[FormatSVG.MOVE_TO_ABSOLUTE];
j = drawMethod(this, svgCmds, j);
// j = createMoveToCommand(svgCmds, j);
break;
....
}
private static function createMoveToCommand(instance:PathToArray, svgCmds:Array, j:int) : int {
// moveTo point
instance.firstP = instance.lastP = new Point(Number(svgCmds[j]), Number(svgCmds[j + 1]));
instance.drawingCommands.push(new FillCommand(instance.fill.color, instance.fill.alpha));
instance.drawingCommands.push(new StyleCommand(instance.stroke.width, instance.stroke.color, instance.stroke.alpha));
instance.drawingCommands.push(new MoveCommand(instance.firstP.clone()));
j += 2;
if (j < svgCmds.length && !isNaN(Number(svgCmds[j]))) {
do {
// if multiple points listed, add the rest as lineTo points
instance.lastP = new Point(Number(svgCmds[j]), Number(svgCmds[j + 1]));
instance.drawingCommands.push(new LineCommand(instance.lastP.clone()));
instance.firstP = instance.lastP;
j += 2;
} while (j < svgCmds.length && !isNaN(Number(svgCmds[j])));
}
return j;
}
Если мы аналогично заменим обращения ко всем методам, станет ли наш код от этого лучше? Нет, только не это.
Мы честно пытались сделать makeDrawCmds лучше и достигли определенных успехов: теперь он читабелен. Но структура кода пока очень жесткая и мы столкнулись с тем, что не можем сделать этот участок лучше.
Стоит ли продолжать?
Нужно уметь остановиться и сказать себе, что время этой части кода еще не наступило.
Позднее, когда архитектура проекта станет лучше, мы вернемся к этому вопросу.