方法需要特定的子类型,但集合是基本抽象类型。有什么问题?

时间:2018-06-12 09:15:05

标签: oop inheritance design-patterns

最近我陷入了这样的境地。我概括了这个问题,因为我认为它与结构设计有关,而不是具体问题。

一般问题

有一个类的层次结构:一个抽象基类Base和一些从中继承的具体结构D1D2D3。类A包含对象的Base类型集合。 A需要从某些服务 - 类B进行计算,但B.process()方法只接受类型为D1的集合。让我们说这很重要,因为如果输入集合包含任何其他类型,则返回的值是错误的。

Class diagram

A有一个接口,允许客户端向内部集合添加元素,而不以任何其他方式公开。可以为同一客户端构建层次结构中的类,并将新值传递给A; A没有足够的上下文来构建它们。

尝试,问题和想法

我最关心的是需要在运行时确定A集合中每个元素的类型,因此可以过滤正确的元素并传递给B.process()。即使有可能(这是我特别的问题,后来更多),这似乎是错的!我认为包含对抽象基类的引用的对象不应该知道它所拥有的具体实例。

我试着:

  • 将参数类型更改为B.process(c: Base[]),因此A不必向下转换类型,但它无法解决任何问题:A仍需要过滤元素或计算将是错误的。
  • 将整个集合Base[]传递给B.process(),但只是将选择/预测问题推迟到B
  • process()中添加Base方法,以便D1可以覆盖行为(众所周知的多态性)。这里的问题是process()返回SomeValue类型只对D1有意义。
  • 分隔添加元素的界面,以便更具体的A.addD1Element(e: D1)方法可以允许将D1个对象放在不同的集合中,并将其传递给B。它应该工作,但也看起来......不知道,很奇怪。如果基于参数类型的方法重载是可能的,那么至少该过程对于该类的客户来说不会那么麻烦。
  • 只需分隔层次结构的D1类。这是前一个更激进的变体。问题是D1 似乎与整个层次结构相关,但B的具体要求除外。

这些是我对这个问题的一些看法。

例如,所使用的语言支持在运行时检查对象的类型(instanceof),并且很容易根据该检查过滤集合。但正如我所说,我的问题与范式更为相关。一个语言怎么样,例如C ++,哪个不那么方便来做这样的检查?

那么什么可以解决这类问题呢?可以应用什么样的重构或设计模式,以便容易处理问题或简单地消失?

This question看起来很相关,但我相信这更为一般(尽管我提供了更具体的背景)。最受欢迎的答案建议分成不同的集合。这也是我考虑的一个想法,但每次添加新类型时都会强制改变A实现。

上下文(行动中的问题)

我以一般的方式提问,因为它确实在这方面引起了我的兴趣,但我知道大多数时候只能通过它试图解决的特定问题的上下文来分析设计。

手头的问题类似于:

A是一个类(某种实体,如DDD实体),它模拟客户招致服务的协议债务 。它有不同的费用,包括每月工资。 Base及相关类别是不同类型的付款。他们有很多共同点,虽然大多数是数据(日期,数量,利益等);但至少有一种类型的付款具有不同的附加信息:每月付款(D1)。这些付款需要仔细分析,以便不同的班级(B)对此负责,使用更多的上下文信息和所有类型的付款。该服务需要特定于这些付款的附加数据,因此无法接收抽象Payment类型(至少不在该设计中)。其他付款没有特定信息MonthlyPayment,因此他们无法生成业务所需的值B正在生成(在其他付款类型中没有意义)。< / p>

所有付款都存储在同一个集合中,因此该类的其他方法可以通用方式处理所有付款

这主要是背景。我认为设计并不是最好的,但我没有看到更好的设计。

如前所述,可能只在另一个集合中分隔MonthlyPaymentD1)?但它并不是唯一需要额外处理的付款(尽管这是最复杂的),因此我可以针对每种付款类型结束不同的集合,而根本不需要任何层次结构。目前有四种付款类型,其中两种需要额外的特定分析,但稍后可以添加更多类型,并且每次添加新类型时都需要修改实施。

这是不同类型的不同集合的更独立的方法,这里更好吗?抽象基类Payment仍可用于可通过公共接口操作的付款。此外,我可以使用层超类型或类似的东西来允许重复使用常用功能(该语言也允许一种混合)并停止使用基类作为来自层次结构的根。

UF。对于文本的篇幅我很抱歉。我希望它至少是可读和清晰的。非常感谢你提前。

0 个答案:

没有答案