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

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

Основной класс — это Board, который представляет собой холст, отвечающий за обработку событий мыши при рисовании фигур. Он также имеет переменные контекста, такие как currentShape или snapFlag, для активации магнетизма сетки.

Для обработки перемещения/изменения размера/вращения фигур они наследуются от стороннего инструмента с открытым исходным кодом, который называется ObjectHandles (flex).

У меня есть baseShape, расширяющий основной класс ObjectHandles, чтобы переопределить некоторые из его внутренних функций, например функцию onMove.

При создании формы (мышь вниз, движение, мышь вверх) это обрабатывается Board, и он знает о своем собственном флаге привязки.

var mouseUpPoint:Point = boardCanvas.globalToLocal(новая точка(event.stageX, event.stageY)); var snapMouseUpPoint = snapPoint(mouseUpPoint.x, mouseUpPoint.y);

В моем переопределенном методе onMove я хотел бы, чтобы форма знала о флаге привязки платы и когда он менялся. Как мне это сделать ?

Должен ли я передавать Board в качестве параметра в моем конструкторе basicShape, чтобы я мог проверить привязку?

Можно ли передать флаг в качестве параметра и заставить все фигуры прослушивать изменения?

Какое самое чистое решение?

Большое спасибо.


person coulix    schedule 24.11.2008    source источник


Ответы (7)


Я бы подошел к этому немного с другой стороны. Я предполагаю, что объект Board сначала перехватывает события мыши, чтобы он мог решить, по какой фигуре был сделан щелчок. Я бы также хотел, чтобы доска ловила движения мыши, передавая правильные (привязанные или непривязанные) координаты «вниз» выбранному объекту Shape, вместо того, чтобы позволить объекту формы понять это.

Это оставляет обработку привязки к сетке Board и избавляет ваш метод Shape объекта onMove от беспорядка.

person e.James    schedule 24.11.2008
comment
На самом деле это не так, он получает его позже. Каждая фигура, использующая objectHandles, знает о своем выборе. Objecthandles имеет менеджер выбора, который может выбирать/отменять выбор/добавлять/удалять. Однако моя доска может знать, когда объект движется. Но уже слишком поздно. - person coulix; 25.11.2008
comment
События идут от ребенка к родителю, доска является родителем. - person coulix; 25.11.2008
comment
Ну, честно говоря, я не думаю, что это правильный способ сделать это. Конечно, это ваш проект, поэтому вы знаете гораздо больше о затратах и ​​преимуществах такого выбора дизайна. Я поддерживаю свой ответ, но я с нетерпением жду возможности прочитать другие ответы. Отличный вопрос! - person e.James; 25.11.2008

Не зная вашего приложения:

Возможно ли, чтобы форма Shape имела собственное поведение «привязки»? То есть можно ли исключить форму из привязки, а другие нет? Если это так, сделайте snapFlag членом Shape. Когда snapFlag установлен на доске, перебирайте свои фигуры и устанавливайте или не устанавливайте в соответствии с вашими правилами.

Если поведение привязки применяется ко всем фигурам на доске, рассмотрите модель, управляемую событиями (если она доступна — я новичок во Flex). Когда фигура движется, она вызывает событие OnMove. После этого Правление может ответить и решить «защелкнуть» форму на место, если это уместно.

Если поведение привязки применимо ко всем фигурам, а события недоступны, я бы просто сказал, что в этом случае к черту слабую связь - сделайте доску фигур осведомленной. Похоже, вы сохраняете кучу кода, используя ObjectHandle. Эта выгода может перевесить стоимость объединения элементов пользовательского интерфейса.

person Corbin March    schedule 24.11.2008
comment
Хм, я могу попытаться ответить на событие onmove, обновив положение формы до режима привязки. Я дам ему попробовать. - person coulix; 25.11.2008

Просто пытаюсь подумать вместе с вами.. Я не вижу ничего особенного в том, что Shapes имеет интерфейс IBoard. Хотя мне не нравится идея, что они должны проверить флажок на доске...

Как бы вы передали флаг в качестве параметра? В методе OnMove()? не совсем понял... не могли бы вы расширить?

Хотя... Если вы попытаетесь немного подумать о SRP - принципе единой ответственности... за что отвечают классы Shape? Да, это уже написал eJames.

Мне кажется, что их основная ответственность, вероятно, НЕ связана с обработкой событий мыши ... здесь нужно больше узнать о вашем приложении, но мое общее мнение заключается в том, почему бы кому-то другому не снять эту мышь, а затем выяснить, что форма должна с ней делать и, например, вызвать Draw() для формы с новыми координатами?

Допустим, вы хотите применить что-то вроде составного шаблона (фигуры внутри фигур...), и вы хотите, чтобы они сами могли обрабатывать эти события мыши... но тогда было бы логично, если бы они восприняли это событие мыши в своем локальном координаты, но тогда я думаю, что вы должны предоставить всю информацию через это событие (локальные координаты, статус мыши...), чтобы им не приходилось запрашивать "глобальные" переменные на доске...

person Paul Kapustin    schedule 24.11.2008

Передача флага в качестве параметра для конструктора формы. Но это не будет хорошо, так как флаг будет меняться, и я должен сделать так, чтобы каждая фигура обновляла свою копию флага при изменении.

Это правда, что ответственность за форму заключается не в том, чтобы знать, как обрабатывать события мыши. Но это то, что делают ObjectHandles: реагируют на события, обновляют параметр поворота высоты и ширины фигуры.

Возможно, мне следует перенести часть кода библиотеки в класс моей доски для управления выбором формы и перемещением/изменением размера/вращением.

person coulix    schedule 24.11.2008
comment
Возможно, вам не придется передавать слишком много. Я бы сказал, что Board должен выполнять быструю и эффективную проверку, чтобы увидеть, в какие прямоугольники фигур попадает щелчок мышью, а затем просто спрашивать эти фигуры: находится ли эта позиция мыши в пределах ваших границ? - person e.James; 25.11.2008
comment
Таким образом, Board обрабатывает общие фигуры, а сами фигуры обрабатывают все кровавые детали, которые делают их уникальными по сравнению с другими фигурами. - person e.James; 25.11.2008

Обработчики объектов OnMouseMove

        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));

Все формы следуют правилу привязки: одна не может быть привязана, а другая свободна.

person coulix    schedule 24.11.2008
comment
Мне нравится эта идея. Если у вас уже есть «родительский» ivar, почему бы не сделать доску родителем фигур верхнего уровня? Когда вы вызываете .globalToLocal для объекта Board, он может при необходимости преобразовать эту точку в точку привязки. - person e.James; 25.11.2008
comment
Хм, да, я должен попытаться переопределить globalToLocal для родителя, которым является плата. Опубликую ответ, когда он заработает - person coulix; 25.11.2008

Решил так:

Поскольку я переопределяю onMouseMove в своем классе baseShape и использую инфраструктуру PureMVC, я только что сообщил baseShape о моем boardMediator.

переопределить защищенную функцию onMouseMove(event: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 были выполнены некоторые дополнительные вычисления, что привело к смещению привязки.

person coulix    schedule 25.11.2008

Используйте ObjectHandles версии 2, а затем создайте ограничение, чтобы делать то, что вы хотите.

person Marc Hughes    schedule 19.03.2010