2010-02-26 6 views
4

У меня есть абстрактный базовый класс T, из которого классы A и B унаследовать. Теперь у меня есть операция (на T), которая требует немного другой реализации в A и B, но большая часть кода такая же. Позвольте мне дать вам пример: Есть две возможности реализовать что-то вроде .Clone метода:OO Pattern: общая работа между абстрактным базовым классом и подклассами

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...)?
+2

Определенно первый метод и шаблон шаблона метода, упомянутый Антоном Гоголевым. –

ответ

2

Если код в базовом классе требуется для клонирования на работу, первый вариант является правильным. Второй вариант позволяет реализовать метод Clone без вызова кода в базовом классе.

Если код в базовом классе не требуется, второй вариант является правильным. Первый вариант не позволяет реализовать метод Clone без вызова кода в базовом классе.

7

Похоже Template method схеме:

Метод шаблон используется для:

  • пусть подклассов реализовать (через метод переопределения) поведения, которые могут изменяться в
  • избежать дублирования в коде : вы ищете общий код в алгоритме и реализуете варианты в подклассах
  • контроль над тем, что пои nt (s) разрешено.
1

В общем, я бы использовал первый подход, поскольку он проще. Однако в некоторых случаях требуется вторая.

Обратите внимание, что использование клонирования объектов в качестве примера может быть не оптимальным. Клонирование является особенным тем, что возвращаемый объект должен быть того же типа, что и клонированный объект, хотя переопределенный метод имеет базовый тип.

Так что у вас есть класс B, который наследуется от А, и вы делаете это:

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

Используя первый подход, клонированный объект должен быть создан, но тип должен быть типа B. Обычно для этого вы используете object.MemberwiseClone(), но это мешает вам заменять поля readonly, поскольку это может быть сделано только в конструкторе (например, клонирование списка, который не должен быть общим для клона и исходного объекта).

1

Первый вариант достаточно справедлив, где есть определенная работа, которая, как вы знаете, будет различной по производным классам. Может быть, вы хотите иметь

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 

И нет, это не делает совершенно здравый смысл для Clone, когда вы смотрите на это, потому что вы собираетесь получить T назад от базовой Clone, и преобразования, что А не все так просто.

Есть еще несколько вариантов, которые вы могли бы рассмотреть.

Один из них - вспомогательный класс. Вместо того, чтобы иметь какой-либо код в T, вам может понадобиться переместить ваш общий код в статический метод статического класса, чтобы избежать дублирования.

Другой оказывает интерфейс ICloner который T понимает контракт, но А и Б понимают реализацию, такие как

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 

Confused еще достаточно?

Смежные вопросы