Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 如何解决UI案例中的并行继承_Oop_User Interface_Inheritance - Fatal编程技术网

Oop 如何解决UI案例中的并行继承

Oop 如何解决UI案例中的并行继承,oop,user-interface,inheritance,Oop,User Interface,Inheritance,我很难理解如何解决并行继承问题 并行继承的定义 Fowler对并行继承的定义如下[1,第68页]: 并行继承层次结构实际上是散弹枪的一个特例 手术。在这种情况下,每次创建一个类的子类, 您还必须创建另一个的子类。你可以认识到这一点 因为一个层次结构中类名的前缀是 与另一层次结构中的前缀相同 问题 书中 作者将显示以下并行继承: 然后,他用合成法解决了并行继承问题,并说: 在许多情况下,并行继承层次结构可以在 这种方式只剩下一个继承层次结构,而 其他继承层次结构的类通过使用进行集成 解决方案如下

我很难理解如何解决并行继承问题

并行继承的定义 Fowler对并行继承的定义如下[1,第68页]:

并行继承层次结构实际上是散弹枪的一个特例 手术。在这种情况下,每次创建一个类的子类, 您还必须创建另一个的子类。你可以认识到这一点 因为一个层次结构中类名的前缀是 与另一层次结构中的前缀相同

问题 书中 作者将显示以下并行继承:

然后,他用合成法解决了并行继承问题,并说:

在许多情况下,并行继承层次结构可以在 这种方式只剩下一个继承层次结构,而 其他继承层次结构的类通过使用进行集成

解决方案如下所示:

因此,作者和Fowler得出结论,并行继承可以用

消除重复的总体策略是确保 一个层次结构的实例引用另一个层次结构的实例

我看到的问题是类仍然存在,如果我添加一个新类,则必须添加一个新的“*ListView”类。

但对于这个问题,福勒说:

如果使用“移动方法”和“移动字段”,则引用对象上的层次结构 阶级消失了

对于当前情况,这意味着我移动该方法以显示实体 在实体类中

这会不会伤害MVC负责人

问题: 那么如何解决并行继承呢 尤其是在UI情况下?

资料来源: Martin Fowler“重构:改进现有代码的设计”


根据具体情况,有几种解决方法。在此,我提出两种可能的解决方案:

注意:我将在示例中使用一些类似scala的伪代码,因为它很短且可读

列出适配器和泛型 基于以下方面的实施:

最初,
ListView
可能有一个默认适配器,它需要适配器实现一些接口,我们称之为
Nameable
。并使用它渲染每个项目

  class BasicListViewAdapter extends ListAdapter[Nameable]

  //on scala it would be a trait, but I'll call it interface just for the sake of the example
  interface Nameable {
    def getName():String
  }
当然,并非所有的类都以完全相同的方式呈现。这可以通过使用适配器来解决

  class Partner  implements Nameable
  class Customer extends Partner { 
    def getName = { this.getClientCode + " " + this.getFullName }
    /* some implementation*/ 
  }
  class Supplier extends Partner { 
    def getName = { this.getCompanyName }
    /* some implementation*/ 
  }
其中,供应商的
列表视图
将生成公司名称列表,客户的
列表视图
将显示客户代码列表及其各自的名称(无论如何,仅举一个例子)

现在,如果我们想制作更复杂的列表,我们可以为ListView提供一个自定义适配器

  class PhoneNumberAdapter extends ListAdapter[Supplier] { /*...*/}

  val supliersWithPhoneNumbers = new ListView
  supliersWithPhoneNumbers.useAdapter(new SupplierWithPhoneNumberAdapter)
使用这种技术,您不再需要为每个模型类定义一个ListView类,而只需要为特殊情况定义自定义适配器。默认适配器和层次结构越好,所需的代码就越少

再举一个例子,你可以看看


混合蛋白/性状 如果你选择的语言允许(如果你在哲学上同意),你可以使用混合词或特征,而不是使用构图。我不会深入讨论两者之间的差异,只使用mixin(更多信息:)

通过使用mixin,您能够以更精细的方式分解行为,解锁各种新模式和解决方案(如果您添加了一些结构类型和其他功能,甚至会更复杂)

例如,回到ListView案例,ListView可以合并每个渲染策略,如下所示:

  trait NameAndPhoneNumber {
    //we require this trait to be incorporated on some class of type ListView
    this:ListView[{def getName:String }] => 

    override def render = ...
  }


  //where ListView is covariant
  new ListView[Supplier] with NameAndPhoneNumber
其中,
name和phonenumber
可以应用于多个类别,而不仅仅是客户或供应商。 事实上,它可能会被重构为:

  new ListView[Supplier] with NameRendering with PhoneRendering
并利用可堆叠特征模式(更多信息(此处)[和(此处)[)

参考资料:

  • 一个案例:
  • (可堆叠特征模式)[

感谢您的努力!我认为适配器可能是同一个问题,因为对于包含不同内容的每个listView,必须创建不同的适配器。对于其他视图,必须为每个实体或内容创建视图。我的观点是,在UI情况下解决并行继承问题没有正确的答案。但再次感谢n:)