2013-07-24 3 views
3

Предполагая, что вы начинаете с этими двумя классами:Является ли это шаблоном проектирования программного обеспечения?

public class Foo{ 
    public virtual Baz Bar(){ 
     return GetStandardBaz(); 
    } 
} 

public class Qux: Foo{ 
    public virtual Baz Bar(){ 
     return GetQuxBaz(); 
    } 
} 

Теперь давайте говорить требование придумывает что-то делать с Baz перед его возвращением, когда Bar вызывается. Я хотел бы создать метод virtual protected и удалить virtual из открытого метода следующим образом:

public class Foo{ 
    public Baz Bar(){ 
     var value = BarInternal(); 
     DoSomethingFirst(value); 
     return value; 
    } 

    protected virtual Baz BarInternal(){ 
     return GetStandardBaz(); 
    } 
} 

public class Qux: Foo{ 
    protected override Baz BarInternal(){ 
     return GetQuxBaz(); 
    } 
} 

Это гарантирует, что всякий раз, когда Bar прибудет называеться, полученный Baz передается в DoSomethingFirst перед возвращением. Да, это измененное изменение для всех дочерних классов, но оно не требует каких-либо обновлений для любых сайтов вызовов Bar.

Это стандартный шаблон дизайна? Есть ли лучший способ, который мне не хватает? Также интересно узнать, есть ли лучшее исправление после исправления, чем Internal.

+1

Есть ли причина не добавлять метод базового класса Baz2 (или NewBaz, или что-то еще)? Таким образом, вы избегаете ломающихся изменений. Для соглашения об именах «Внутренний» не является ужасным. «Impl» также распространен. – ThatBlairGuy

+2

Вы имеете в виду 'override' в' Qux'? – dtb

+0

Отвечая на мой собственный вопрос - требование не затрагивать места, вызывающие Baz(), недействительно. Методы в производных классах, которые вызывают Baz(), должны быть изменены, и в зависимости от обстоятельств (например, кто-то другой, использующий вашу библиотеку) у вас может не быть доступа к этому коду. Добавление нового метода с новым поведением - лучшая практика. – ThatBlairGuy

ответ

2

Если вы немного изменили класс Foo, вы получите Template Method pattern.

public class Foo{ 
    public Baz Bar(){ 
     var value = BarInternal(); 
     DoSomethingFirst(value); 
     return value; 
    } 

    protected virtual Baz BarInternal(){ 
     return GetStandardBaz(); 
    } 
} 

Вы можете достичь что-то подобное с Decorator pattern, а также. Решение будет зависеть от деталей того, что ваши классы должны делать.

+0

После прочтения страницы в Википедии я должен согласиться с тем, что это в целом пример шаблона шаблона, но я думал, что процесс разоблачения открытого метода в базовом классе и имеющий виртуальный метод Core будет более конкретно – Daryl

1

Это хорошо, потому что вы можете фильтровать входы и выходы стандартным способом. Вы можете выполнить проверку и дополнительную обработку.

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

Обычно я использую суффикс «Core» (GetBarCore).