Концептуальный вопрос: слабая связь
Я строю проект, похожий на графическую доску, где я сталкиваюсь с проблемой дизайна.
Основным классом является Board - это холст, отвечающий за обработку событий мыши при рисовании фигур. У этого также есть переменные контекста, такие как currentShape или snapFlag, чтобы активировать магнетизм сетки.
Для обработки перемещения / изменения размера / поворота фигур они наследуются от стороннего инструмента с открытым исходным кодом под названием ObjectHandles (flex).
У меня есть baseShape, расширяющий основной класс ObjectHandles для переопределения некоторых его внутренних функций, таких как функция onMove.
При создании фигуры (мышь вниз, движение, мышь вверх) Совет обрабатывает ее и знает о своем собственном флаге привязки.
var mouseUpPoint: Point = boardCanvas.globalToLocal (новая точка (event.stageX, event.stageY)); var snapMouseUpPoint = snapPoint(mouseUpPoint.x, mouseUpPoint.y);
В моем методе overidden onMove я бы хотел, чтобы фигура знала флаг привязки Board и когда он менялся. Как мне это сделать?
Передам ли я Board в качестве параметра в конструкторе basicShape, чтобы я мог проверить привязку?
Я передаю флаг как параметр и каким-то образом заставляю все формы прислушиваться к изменениям?
Какое самое чистое решение?
Большое спасибо.
7 ответов
Я бы подошел к этому с несколько иной точки зрения. Я предполагаю, что Board
сначала объект перехватывает события мыши, чтобы он мог решить, какая фигура была нажата. Я бы тоже имел движения мыши на доске, передавая правильные (привязанные или не привязанные) координаты "вниз" к выбранным Shape
объект, вместо того, чтобы позволить объекту формы понять это.
Это оставляет обработку привязки сетки к Board
и держит ваши Shape
объект onMove
метод без беспорядка.
Не зная вашего приложения:
Возможно ли когда-либо, чтобы у Shape было собственное поведение "привязки"? То есть форма может быть исключена из привязки, а другие нет? Если это так, сделайте snapFlag членом Shape. Когда SnapFlag установлен на доске, перебирайте фигуры и устанавливайте или не устанавливайте в соответствии с вашими правилами.
Если поведение привязки применяется ко всем фигурам на плате, рассмотрите модель, управляемую событиями (если она доступна - я нуб Flex). Когда Shape перемещается, он вызывает событие OnMove. Затем Правление может ответить и принять решение "привязать" Форму к месту, если это необходимо.
Если поведение привязки применяется ко всем фигурам, а события недоступны, я бы просто сказал, что в этом случае, черт возьми, со слабой связью - проследите за советом фигур. Похоже, вы сохраняете кучу кода с помощью ObjectHandle. Это преимущество может перевесить стоимость сопряжения ваших элементов пользовательского интерфейса.
Решил это так:
Так как я переопределил onMouseMove в своем классе baseShape и использую платформу PureMVC, я просто сделал baseShape осведомленным о моем boardMediator.
переопределить защищенную функцию onMouseMove(событие:MouseEvent): void { [...]
// added on override
var board:BoardMediator = ApplicationFacade.getInstance().retrieveMediator(BoardMediator.NAME) as BoardMediator;
затем
desiredPos = board.snapPoint(desiredPos.x, desiredPos.y);
Может быть, не очень красиво, но это работает, o Переопределение метода globalToLocal в моем представлении на плате тоже сработало, но в onMouseMove было выполнено еще несколько вычислений, что привело к перемещению без выравнивания.
Просто пытаюсь думать вместе с тобой... Я не вижу ничего особенного в Shapes, имеющем интерфейс IBoard. Хотя мне не нравится идея, что они должны проверять флаг на доске...
Как бы вы передали флаг в качестве параметра? В методе OnMove()? не очень хорошо понял это... не могли бы вы расширить?
Хотя.. Если вы попытаетесь немного подумать о SRP - принципе единой ответственности... какова ответственность классов Shape? Да, это то, что eJames уже написал.
Мне кажется, что их основная ответственность, вероятно, не в том, чтобы обрабатывать события мыши... здесь нужно больше узнать о вашем приложении, но мое общее чувство заключается в том, почему бы не кому-то другому опустить эту мышь, а затем выяснить, что форма должна с ней делать и, например, вызвать Draw() на Shape с новыми координатами?
Допустим, вы хотите применить что-то вроде Composite pattern (Shapes inshape...) и хотите, чтобы они могли обрабатывать эти события мыши сами... но тогда было бы логично, если бы они воспринимали это событие мыши в своей локальной среде. координаты, но тогда я думаю, что вы должны предоставить всю информацию через это событие (локальные координаты, состояние мыши...), чтобы им не нужно было запрашивать "глобальные" переменные на доске...
Передача флага в качестве параметра для конструктора фигур. Но это не будет хорошо, так как флаг будет меняться, и я должен сделать каждую фигуру, чтобы обновить копию своего флага при изменении.
Это правда, что ответственность за форму не в том, чтобы уметь обрабатывать события мыши. Но это то, что делают ObjectHandles: реагируют на события, обновляют параметр поворота ширины по высоте фигуры.
Может быть, я должен передать часть библиотечного кода в моем классе доски для обработки выбора формы и перемещения / изменения размера / вращения.
OnMouseMove ObjectHandles
protected function onMouseMove(event:MouseEvent) : void
{
if( ! visible ) { return; }
if( ! event.buttonDown )
{
setMouseCursor( event.stageX, event.stageY );
return;
}
if(parent == null )
{
return;
}
var dest:Point = parent.globalToLocal( new Point(event.stageX, event.stageY) );
var desiredPos:Point = new Point();
var desiredSize:Point = new Point();
var desiredRotation:Number = 0;
... plenty more
then
if( wasMoved ) { dispatchMoving() ; }
if( wasResized ) { dispatchResizing() ; }
if( wasRotated ) { dispatchRotating(); }
Поэтому я не могу прослушать событие перемещения и сказать доске, чтобы оно щелкнуло, поскольку фигура уже движется свободно. Я должен добавить оснастку здесь:
var dest: Point = parent.globalToLocal (новая точка (event.stageX, event.stageY));
Все формы следуют правилу привязки, не может быть одного щелчка, а другого - свободного.
Используйте ObjectHandles версии 2, а затем создайте ограничение, чтобы делать то, что вы хотите.