【问题标题】:OO Pattern: Shared work between abstract base class and subclassesOO 模式:抽象基类和子类之间的共享工作
【发布时间】:2011-01-21 09:23:55
【问题描述】:

我有一个抽象基类T,类AB 继承自该类。我现在有一个操作(在T 上),它需要在AB 中稍微不同的实现,但大部分代码是相同的。让我举个例子:有两种可能实现类似.Clone 的方法:

Public MustInherit Class T
    Protected MustInherit Function _DoClone() As T

    Public Function Clone() As T
        Dim clone = Me._DoClone()    ' do the subclass-specific stuff '
        ... ' do the shared stuff '
    End Function
End Class

Public Class A
    Inherits T

    Protected Overrides Function _DoClone() As T
        ... ' do the subclass-specific stuff '
    End Function
End Class

Public MustInherit Class T
    Protected Sub _DoClone(clone As T)
        ... ' do the shared stuff '
    End Function

    Public MustInherit Function Clone() As T
End Class

Public Class A
    Inherits T

    Public Overrides Function Clone() As T
        Dim clone = ... ' do the subclass-specific stuff '
        Me._DoClone(clone)
    End Function
End Class

(示例是在 VB.NET 中,但同样的问题适用于 C#、Java 等)

我的问题:

  • 是否有明确首选的选项?
  • 这是一个有名字的众所周知的模式吗(这样我可以做更多的研究)?
  • 对于此类情况(即 _Do... 事物)是否有完善的命名约定?

【问题讨论】:

  • 绝对是第一种方法,它是 Anton Gogolev 提到的模板方法模式。

标签: .net language-agnostic oop


【解决方案1】:

看起来像Template method 模式:

模板方法用于:

  • 让子类实现(通过方法覆盖)可以变化的行为
  • 避免代码中的重复:您在算法中寻找通用代码,并在子类中实现变体
  • 控制在什么时候允许子类化。

【讨论】:

    【解决方案2】:

    如果克隆工作需要基类中的代码,则第一个选项是正确的。第二个选项允许您在不调用基类中的代码的情况下实现 Clone 方法。

    如果不需要基类中的代码,则第二个选项是正确的。第一个选项不允许您在不调用基类中的代码的情况下实现 Clone 方法。

    【讨论】:

      【解决方案3】:

      一般我会使用第一种方法,因为它更简单。但是,在某些情况下,第二个是必需的。

      请注意,以对象克隆为例可能不是最佳选择。克隆的特殊之处在于返回的对象必须与要克隆的对象具有相同的类型,即使重写的方法是基类型。

      所以假设你有一个继承自 A 的类 B,你这样做:

      A a = new B();
      B b = (B)a.Clone();
      

      使用第一种方法,克隆对象必须由 A 创建,但类型必须是 B 类型。通常您将使用 object.MemberwiseClone() 来实现这一点,但这会阻止您替换只读字段,因为只能在构造函数中完成(例如克隆一个不能被克隆和原始对象共享的 List)。

      【讨论】:

        【解决方案4】:

        第一个选项足够公平,因为您知道在派生类中会有不同的特定工作。也许你想拥有

        Public MustInherit Class T
            Protected MustInherit Function Clone() As T
        
            Public Function CloneAdjusted() As T
                Dim clone = Me.DoClone()
                ' Adjust clone '
            End Function
        End Class
        
        Public Class A
            Inherits T
        
            Protected Overrides Function Clone() As T
                ' Make exact copy of A '
            End Function
        End Class
        

        如果您只是想克隆任何旧的 T 但想在子类中进行小幅调整,则第二种方法会更合适。但在这种情况下,请覆盖 Clone 方法,而不是使用新名称创建一个新方法。例如

        Public MustInherit Class T
            Public Overridable Function Clone() As T
                Dim clone = ' Clone a T here '
            End Function
        End Class
        
        Public Class A
            Inherits T
        
            Public Overrides Function Clone() As T
                ' Any pre-clone work '
                T obj = MyBase.Clone()
                ' Any post-clone work '
            End Function
        End Class
        

        不,这对于克隆来说并不完全有意义,当您查看它时,因为您将从基本克隆中得到一个 T,而将其转换为 A 并不是全部容易。

        您可以考虑其他几个选项。

        一个是辅助类。与其在 T 中包含任何代码,您可能希望将通用代码移出到静态类的静态方法中以避免重复。

        另一个是有一个 ICloner 接口,T 了解其合同,但 A 和 B 了解实现,例如

        Public MustInherit Class T
            Protected ICloner Cloner
        
            Public Overridable Function Clone() As T
                ' Common Code '
                Dim clone = Cloner.GetClone()
                ' More Common Code '
            End Function
        End Class
        
        Public Class A Inherits T
            Public Sub New()
                Cloner = New ACloner(Me)
            End Sub
        End Class
        

        够困惑了吗?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-08
          • 1970-01-01
          • 2012-04-16
          • 1970-01-01
          • 2011-02-09
          • 1970-01-01
          • 2023-03-20
          • 2011-02-09
          相关资源
          最近更新 更多