我过去曾经使用过MVP和MVC,我更喜欢MVP,因为我认为它可以更好地控制执行流程。
我已经创建了我的基础结构(数据存储/存储库类),并且在对示例数据进行硬编码时可以毫无问题地使用它们,因此现在我转向GUI并准备我的MVP。
A节
我已经看到MVP使用视图作为入口点,也就是说,在视图构造方法中,它创建了演示者,该演示者又创建了模型,并根据需要连接事件。
我还以演示者为切入点,在其中创建了视图,模型和演示者,然后在其构造函数中为该演示者提供了视图和模型对象以关联事件。
与2中一样,但是模型没有传递给演示者。相反,该模型是一个静态类,在其中调用方法并直接返回响应。
B区
在使视图和模型保持同步方面,我已经看到了。
每当视图中的值发生更改时,即
TextChanged
.Net / C#中的事件。这会触发一个DataChangedEvent
传递到模型中的,以使其始终保持同步。在模型发生变化的地方(即它侦听的后台事件),然后通过引发的相同想法来更新视图DataChangedEvent
。当用户想要提交更改SaveEvent
时,它将触发,并进入模型进行保存。在这种情况下,模型将模仿视图的数据并处理动作。与#b1相似,但是视图并非始终与模型同步。相反,当用户想要提交更改时,将
SaveEvent
被解雇,演示者获取最新的详细信息并将其传递到模型中。在这种情况下,除非需要对视图数据进行操作,否则模型将不知道视图数据,在这种情况下,将传递所有必需的详细信息。
C区
在视图中显示业务对象,即不是原始数据的对象(MyClass)(int,double)
该视图具有将显示为域/业务对象的所有数据的属性字段。例如,
view.Animals
公开一个IEnumerable<IAnimal>
属性,即使视图将它们处理到TreeView中的Nodes中。然后对于选定的动物,它将SelectedAnimal
作为IAnimal
属性公开。该视图不了解域对象,它仅公开图元/框架(.Net / Java)包含的对象类型的属性。在这种情况下,演示者将把适配器对象传递给域对象,然后适配器将给定的业务对象转换为视图上可见的控件。在这种情况下,适配器必须有权访问视图上的实际控件,而不仅仅是任何视图,因此会变得更加紧密。
D区
用于创建单个控件的多个视图。即,您有一个具有简单模型的复杂视图,例如保存不同类型的对象。您可以在侧面有一个菜单系统,每单击一个项目就会显示相应的控件。
您创建一个巨大的视图,其中包含通过视图界面公开的所有单个控件。
您有几种看法。您有一个菜单视图和一个空白面板。该视图创建所需的其他视图,但不显示它们(visible = false),该视图还为其包含的每个视图(即子视图)实现接口,因此可以向一个演示者公开。空白面板中将填充其他视图(
Controls.Add(myview)
)和((myview.visible = true
)。这些“子”视图中引发的事件由父视图处理,父视图又将事件传递给演示者,反之亦然,以将事件提供给子元素。每个视图(无论是主要父视图还是较小的子视图)均连接到自己的演示者和模型中。您可以从文化上将视图控件放到现有的表单中,它将具备功能,只需将其连接到幕后的演示者中即可。
E节
如果所有内容都具有接口,那么现在基于以上示例中MVP的完成方式,由于它们可能不是交叉兼容的,因此将影响此答案。
一切都有界面,视图,演示者和模型。然后,显然每个都有具体的实现。即使您只有一个具体的视图,模型和演示者。
视图和模型具有接口。这允许视图和模型不同。演示者创建/获得视图和模型对象,并且仅用于在它们之间传递消息。
仅视图具有界面。该模型具有静态方法,不会创建,因此不需要接口。如果需要其他模型,则演示者将调用一组不同的静态类方法。由于模型是静态的,因此与演示者没有链接。
个人想法
从我介绍的所有不同变体中(大多数我可能已经以某种形式使用过),我确信还有更多。我更喜欢A3,因为它可以使业务逻辑在MVP之外可重用,而B2则可以减少数据重复和触发事件。C1用于不添加其他类,请确保将少量非单元可测试的逻辑放入视图中(如何可视化域对象),但是可以对其进行代码审查,也可以在应用程序中简单地对其进行查看。如果逻辑很复杂,我会同意一个适配器类,但并非在所有情况下都同意。对于D部分,我觉得D1创建的视图对于菜单示例来说至少太大了。我以前用过D2和D3。D2的问题是,您最终不得不编写大量代码才能将事件往返于演示者与演示者之间路由到正确的子视图,并且其拖放操作不兼容,每个新控件都需要更多接线才能支持单个演示者。D3是我的首选,但是即使视图恰好非常简单或不需要重用,D3仍会作为演示者和模型添加更多类来处理该视图。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能过头了,因为我已经对域/业务对象进行了此操作,因此这样做通常不会在“设计”中看到任何优势,但它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能会过时了,我已经对域/业务对象进行了此操作,并且这样做通常不会在“设计”中看到任何优势,但是它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。我认为根据情况,D2和D3的混合效果最好。对于E部分,我认为具有接口的所有内容都可能会过时了,我已经对域/业务对象进行了此操作,并且这样做通常不会在“设计”中看到任何优势,但是它确实有助于在测试中模拟对象。我个人认为E2是经典的解决方案,尽管我以前在2个项目中使用过E3。
题
我是否正确实施MVP?有正确的方法吗?
我已经读过Martin Fowler的著作,其中有很多变化,而且我还记得当我刚开始做MVC时,我理解了这个概念,但是最初无法确定切入点在哪里,一切都有自己的功能,但是控制和创建原始作品的是什么MVC对象集。