Нет, декоратор не должен быть абстрактным.
В примере Википедии реализовано 2 типа функциональности:
- Делегирование экземпляру которые должны быть украшены
- Изменение функциональности украшенного объекта
В примере из Википедии классы имеют только 2 метода. Вот почему это не очевидно, если перенос функций делегирования в отдельный класс имеет какой-либо смысл. Логика c CoffeeDecorator могла бы быть реализована непосредственно в классах WithMilk и WithSprinkles. Но если вы хотите украсить класс, имеющий 20-30 методов, то имеет смысл проектировать классы, как на этой странице Википедии: вы помещаете чистый делегирующий logi c в один класс и logi c Speci c для конкретного декоратора к его подклассу. Подумайте о разделении интересов .
С такой конструкцией легче тестировать и поддерживать код. Тестирование базового класса декоратора легко, потому что каждый из его методов должен делать то же самое, что и метод декорированного объекта. А тестирование конкретного декоратора означает «просто» тестирование (обычно) нескольких переопределенных методов. Когда вы анализируете ошибку или хотите расширить декоратор, вы хорошо знаете ответственность каждого класса.
Должен ли базовый декоратор быть абстрактным? Нет, но это может быть полезно. Если вы сделаете базовый класс декоратора неабстрактным, каждый разработчик сможет создать его экземпляр. Но этот базовый класс не имеет никакой дополнительной бизнес-функциональности по сравнению с декорированным классом, где это означает некоторые потери производительности. Чтобы избежать ненужных накладных расходов, имеет смысл объявить этот класс абстрактным.