Ответ
Да, применял, но с осторожностью, предпочитая композицию там, где это уместно. Классический пример использования — создание иерархии исключений или абстрактных классов с общим поведением.
Пример из проекта на C#: У нас была система обработки документов с базовым абстрактным классом DocumentProcessor.
public abstract class DocumentProcessor
{
public abstract string DocumentType { get; }
// Общий шаблонный метод
public ProcessingResult Process(byte[] data)
{
Validate(data);
var parsedData = Parse(data);
return Save(parsedData);
}
protected abstract void Validate(byte[] data);
protected abstract DocumentData Parse(byte[] data);
protected abstract ProcessingResult Save(DocumentData data);
}
public class InvoiceProcessor : DocumentProcessor
{
public override string DocumentType => "Invoice";
protected override void Validate(byte[] data) { /* специфичная для инвойса валидация */ }
protected override DocumentData Parse(byte[] data) { /* парсинг XML инвойса */ }
protected override ProcessingResult Save(DocumentData data) { /* сохранение в БД */ }
}
// Использование
DocumentProcessor processor = new InvoiceProcessor();
var result = processor.Process(fileBytes);
Почему не всегда наследование: В другом модуле, где сущности User, Admin, Moderator имели разные наборы прав, мы использовали композицию через паттерн «Роли» (Role Pattern), чтобы избежать взрывного роста глубины наследования (проблема «Бриллиантового наследования») и сделать систему гибче для добавления новых прав.