Концептуальный вопрос: слабая связь

Я строю проект, похожий на графическую доску, где я сталкиваюсь с проблемой дизайна.

Основным классом является 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, а затем создайте ограничение, чтобы делать то, что вы хотите.

Другие вопросы по тегам