Design patterns MVP中的组合与继承

Design patterns MVP中的组合与继承,design-patterns,user-interface,inheritance,mvp,composition,Design Patterns,User Interface,Inheritance,Mvp,Composition,我正在使用MVP模式开发一个大型应用程序。在开发过程中,我提出了一个问题:是否应该使用组合还是继承。例如:假设我有一个名为Foo的表单,其中包含a和B字段。在应用程序的其他部分中,我有一个表单栏,它具有相同的字段a和B,但有一个额外的字段C 目前,代码是使用继承方法编写的,其中表单栏的视图继承自表单Foo。然后,演示者处理与模型稍有不同的数据。这很简单,但我不知道if是否遵循“is A”的经验法则,因为即使表单不同,它们也处理公共输入(A和B) 然而,在这里,我一直在思考“组合重于继承”和“继承

我正在使用MVP模式开发一个大型应用程序。在开发过程中,我提出了一个问题:是否应该使用组合还是继承。例如:假设我有一个名为Foo的表单,其中包含aB字段。在应用程序的其他部分中,我有一个表单,它具有相同的字段aB,但有一个额外的字段C

目前,代码是使用继承方法编写的,其中表单栏的视图继承自表单Foo。然后,演示者处理与模型稍有不同的数据。这很简单,但我不知道if是否遵循“is A”的经验法则,因为即使表单不同,它们也处理公共输入(A和B)

然而,在这里,我一直在思考“组合重于继承”和“继承”,并且开始认为我应该使用组合而不是继承。然而,由于我使用MVP,它比预期的要复杂,因为我必须为表单Foo设置一个带字段aB的演示者,然后为Bar设置一个带字段C的演示者,并对Foo的演示者进行引用,以便它可以注入将AB字段插入其中

问题是,它已经被证明是更多的代码,因为我必须在Foo的presenter中添加一些排序getter和setter,以便它能够将数据传递到Bar。这感觉就像我打破MVP来提供构图

因此,我的问题是:

对于我的案例来说,使用组合而不是继承真的更好吗?为什么?

使用组合是否会“破坏”MVP

当表单不同时,它们处理公共输入(A和B)

这意味着Foo presenter在概念上不同于Bar presenter,只是碰巧共享一些公共输入,所以它们不应该通过继承来关联。将处理公共输入的代码提取到实用程序类中,并在Foo presenter和Bar presenter中重用这些代码

如果Foo的概念发生变化,它将不会影响Bar(反过来说:如果Bar的概念不能在不改变Foo的概念的情况下发生变化,那么它就是一个“is A”关系,并且确实可以使用继承)


当有疑问时,总是选择组合

当然,当Foo不扩展Bar时,您需要添加更多代码,因为您有额外的getter和setter。但最大的好处是Foo不再依赖酒吧了。这看起来可能是一个很小的好处,但是想象一下,如果您将Inhenrition与50多个类一起使用,它会是什么样子。。。这将是地狱,没有任何逻辑,如果您必须更改一个由其他几个类扩展的类中使用的组件,这将是非常复杂的


出于维护原因,避免使用继承。正如你所说,“酒吧不是Foo”,所以酒吧不应该扩展Foo。根据我的经验,继承从来都不是一个好的解决方案,应该只用于一系列类(例如,当使用复合模式时)。

更干净的组合应该是有类:

型号:A、B、C、Foo、Bar
视图:视图、BView、CView、FooView、BarView
呈现者:呈现者、b呈现者、c呈现者、食品呈现者、酒吧呈现者

其中FooView包含一个AView和一个BView, BarView包含AView、BView和CView 而呈现者有着相似的构成

这种组合使A、B和C(以及它们的视图和呈现者)模块化,因此您可以随意混合和匹配,复合类(Foo和Bar)处理集成

这可以与继承一起使用:
如果Bar是Foo的一个特例,那么Bar应该从Foor继承,而BarPresentor可以从fooppresentor继承。然而,我会考虑以更一般的方式继承视图,因为视图可能或不适合继承,这取决于它们的行为。

让我们从基本知识开始,您必须知道关于类的最重要的事情,即子类也是超类的完整实例。因此,如果在超类中定义字段变量,则在创建子类的实例时,始终会创建此字段。您可以使用super.getVariable()在子类中获取该变量以重用字段(类变量、字段、标志,这在OO编程中都是一样的)。但是您也可以从外部调用SubassInstance.getVariable(),您将得到相同的字段(无需通过子类对其进行任何更改)。因此,您通常根本不需要在子类中调用“super”,因为您通常只想从外部获取/设置它的超类(包括抽象类!)的字段。由于您应该始终将字段变量设置为private,因此我始终建议不要调用“super”来访问任何字段变量(因为即使使用super,您也无法访问超类的私有方法/字段……实际上这是Java中最大的错误之一,因为它无法向其他类提供类树的完整封装……因此您需要调用通常受

保护的
方法,如super.getField(),这很烦人但很必要)

现在让我们从数据模型开始:您有modelA和modelB。您可以从超类继承它们,也可以仅从对象继承它们。但是,如果您仅从对象继承,您可以定义一个简单的(Java!)接口,并将此接口实现到modelA和modelB中。然后您只需通过接口处理这两个类(它们都是如果您有由modelA和modelB组成的modelC,您只需使用一个实例(有时还调用