所以我正在我正在这里工作的一个应用程序上实现类似svg编辑器的GUI。这些是其中需要的逻辑的一些例子:
等等。
我已经实现了所有这些项目,但我不喜欢最终结果,主要是因为我不得不使用大量标记来操纵状态(鼠标点击&& left button&& not移动?做这个),当然这个代码可以更优雅。所以我研究了一下,然后选择了这些选项:
管道模式:我会创建分别处理每个逻辑事件的类,并使用优先级顺序提供首先要做什么/将要交给什么,以及事件将如何传播到后续的管道项目。
MVC:这是最常见的回复,但我现在用它来使代码更干净对我来说非常模糊。
状态机:这样会很好但管理状态机的粒度会很复杂
所以我问S.O.关于如何构建更好,更快乐的代码的技巧大师。
答案 0 :(得分:6)
我建议将UI输入映射到特定操作的逻辑分离到专用对象中。让我们称它们为传感器对象。不知道你的实现语言,我会对此有所了解,但你应该明白这一点。
OperationSensor
+ OnKeyDown
+ OnKeyPress
+ OnKeyUp
+ OnLeftMouseDown
+ OnLeftMouseUp
+ OnNodeSelect
+ OnNodeDeselect
+ OnDragStart
+ OnDragStop
假设您有一个集中了所有各种UI输入的中心类UiInputManager
。它使用特定于语言的机制来监听键盘和鼠标输入。它还可以检测基本操作,例如检测到鼠标是否被按下然后移动,这是一个逻辑“拖动”。
UiInputManager
// event listeners
+ keyboard_keydownHandler
+ keyboard_keyupHandler
+ mouse_leftdownHandler
+ mouse_rightdownHandler
// active sensor list, can be added to or removed from
+ Sensors
UiInputManager不负责了解这些输入导致的操作。它只是以语言特定的方式通知其传感器。
foreach sensor in Sensors
sensor.OnDragStarted
或者,如果传感器侦听由UiInputManager发出的逻辑事件
RaiseEvent DragStarted
您现在拥有的是将输入路由到OperationSensor子类的管道。每个OperationSensor都具有与单个操作相关的逻辑。如果它检测到操作符合条件,则会创建相应的Command对象并将其传回。
// Ctrl + zooms in, Ctrl - zooms out
ZoomSensor : OperationSensor
override OnKeyDown
{
if keyDown.Char = '+' && keyDown.IsCtrlDepressed
base.IssueCommand(new ZoomCommand(changeZoomBy:=10)
elseif keyDown.Char = '-' && keyDown.IsCtrlDepressed
base.IssueCommand(new ZoomCommand(changeZoomBy:=-10)
}
我建议命令对象从传感器传递到UiInputManager。然后管理员可以将它们传递到您的命令处理子系统。这使管理员有机会通知传感器操作已完成,允许他们在需要时重置其内部状态。
可以通过两种不同的方式处理多步操作。您可以在SensorOperation内部实现内部状态机,也可以使用“步骤1”传感器创建“步骤2”传感器并将其添加到活动传感器列表中,甚至可能从列表中删除自身。当“步骤2”完成时,它可以重新添加“步骤1”传感器并自行移除。
答案 1 :(得分:3)
位在节目的后期,但我想补充说,这个的常见模式是中介模式,您可以将各个节点之间的交互的复杂性移动到单独的类中,调解员(比如说ConnectionCreator类)。请参阅Gamma及其同事的designpatterns:http://ebookbrowse.com/addison-wesley-gamma-helm-johnson-vlissides-design-patterns-elements-of-reusable-object-oriented-pdf-d11349017
答案 2 :(得分:2)
Martin Fowler对MVC和相关模式有a good writeup。此外,您可能需要查看command pattern,以便让UI元素了解它们应该如何表现(例如,当点击节点时应移动它或删除它等等。)
答案 3 :(得分:0)
对于UI来说,MVC现在非常普遍。非常简单地说,M(模型)包含状态,V(视图)显示可视元素,C(控制器)调度入站用户操作,例如鼠标点击。目标是模型不直接关注视图,除了可能触发事件。
我或许会把这些聪明的东西放在'在模型中。该模型将知道何时选择节点,其相邻节点形成多边形,状态机等。此设计为您提供了多种好处。它独立于UI渲染的细节;这样您就可以在不中断核心功能的情况下进行主要视图更改。它还使单元测试变得更加容易。