【问题标题】:Building a structure/object in a place other than the constructor在构造函数以外的地方构建结构/对象
【发布时间】:2012-11-05 19:57:08
【问题描述】:

我有代表同一个业务实体的不同类型的对象。 UIObject、PowershellObject、DevCodeModelObject、WMIObject 都是对同一实体的不同表示。

假设实体是Animal,那么我有AnimalUIObject、AnimalPSObject、AnimalModelObject、AnimalWMIObject等。

现在AnimalUIObject、AnimalPSObject、AnimalModelObject 的实现都在单独的程序集中。

现在我的情况是我想验证业务实体Animal 的内容,而不管它来自哪个程序集。所以我创建了一个GenericAnimal 类来表示Animal 实体。

现在在 GenericAnimal 我添加了以下构造函数:

GenericAnimal(AnimalUIObject)
GenericAnimal(AnimalPSObject)
GenericAnimal(AnimalModelObject)

基本上我让GenericAnimal 依赖于所有底层程序集,以便在验证时处理这个抽象。

现在另一种方法是让GenericAnimal 带有一个空的构造函数 允许这些底层程序集有一个Transform() 方法,该方法将构建GenericAnimal。

这两种方法各有利弊:

第一种方法:
优点:所有构造逻辑都在一个类中的一个地方GenericAnimal
缺点:GenericAnimal class 必须在每次有新的表示形式时都被触及。

第二种方法:
优点:将构建责任委托给底层程序集。
缺点:由于构造逻辑分布在程序集中,明天如果我需要在GenericAnimal 中添加属性X,那么我必须触摸所有程序集以更改Transform 方法。

哪种方法看起来更好?
或者您认为哪个是较小的邪恶?
有没有比以上两种更好的替代方法?

只是根据我收到的 cmets 进一步详细说明。 我没有修改底层对象结构的奢侈,即我无法更改 AnimalUIObject AnimalPSObject 等。GenericAnimal 是我仅为验证目的而引入的构造。

【问题讨论】:

  • 我注意到 .NET 术语 - 为什么是 Java 标记?
  • 虽然术语是 .Net,但问题确实与语言无关。
  • 我认为您真的可以在这里使用比Animal 更好的东西作为示例。
  • 理想情况下,所有对象都应该实现相同的接口。如果你有能力改变它们,我会考虑这样做。否则你应该实现必要的包装器。

标签: c# java ooad


【解决方案1】:

我有不同类型的对象代表同一个业务 实体。 UIObject、PowershellObject、DevCodeModelObject、WMIObject 全部 是对同一实体的不同表示。

看一下Design Patterns,尤其是Structural Pattern。

据我了解,Decorator Pattern 会很有用:

装饰器模式可以用来扩展(装饰) 运行时某个对象的功能,独立于其他对象 同一类的实例,前提是在完成一些基础工作 设计时间。这是通过设计一个新的装饰器类来实现的 包装原来的类

所以它应该是第一种方法,但没有缺点:

GenericAnimal 类将有一个构造函数:

GenericAnimal(AnimalObject)

AnimalObject 可以是接口或抽象类。

缺点:GenericAnimal 类必须在每次有新的时候都被触及 表示形式。

如果您添加另一个表示形式,则使其实现或扩展AnimalObject。

【讨论】:

    【解决方案2】:

    可能是抽象工厂模式的机会?

    【讨论】:

    • 所有这些类型都不能扩展/包含 GenericAnimal。 GenericAnimal 是稍后引入的仅用于验证目的的构造,所有多个实现都存在没有 GenericAnimal。
    【解决方案3】:

    我认为这两种方法都很“邪恶”。

    我认为您真正需要的是从 Animal 类作为您的核心类开始,并将其余的类包装类使用 Animal 类来保存表示。然后针对 Animal API 执行验证。

    【讨论】:

    • + 我也觉得外露的设计好像倒退了。你打败了我,说不出话来。 :)
    • 但是我没有修改底层对象结构的奢侈。详细说明我们有多个 API 可以从中获取这些不同类型的对象。我们为每个入口点提供了包装程序集,以获取动物实体。现在,当我在将这些对象传递给验证层之前获取这些对象时,我必须将它们转换为 GenericAnimal。我的问题基本上是这种转换应该在 GenericAnimal 类构造函数中还是作为每个 Wrapper 程序集中的 Transform 方法?
    • @VishalNaidu - 我明白你的问题。正确的解决方案是修改底层对象结构。这不是奢侈品……这是必需品(IMO)。如果您不能这样做,那么您提出的两种解决方案(IMO)同样糟糕。两者都会导致重复代码和更多潜在错误。
    • 底层代码是生产代码。我不能碰那个。我将编写的验证码不会发货。所以你提出的解决方案将是不可接受的。进一步补充说,所有这些表示都来自不同的客户端,例如 Powershell/UI,它们有自己的实体表示,我不能因为验证而中断。
    • 因此,如果您因为生产代码设计不佳而不得不编写邪恶(测试)代码,那就去做吧。但我来自哪里,修复设计不良的生产代码是一件好事。 “我不能碰它”表示您的组织(或客户组织)的开发过程中出现了功能障碍。
    猜你喜欢
    • 1970-01-01
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 2021-10-22
    • 1970-01-01
    • 2016-02-10
    相关资源
    最近更新 更多