Я предположил бы, что объект - таймер создает или использует рабочий поток в целях запустить события таймера. Расположить вызов освободит поток и ресурсы, связанные с ним. Если это так, это была бы хорошая идея звонить, располагают так, у Вас нет неиспользованных потоков, бродящих вокруг слишком долго.
Как первое практическое правило, я предпочитаю абстрактные классы интерфейсам на основе Руководства по проектированию .NET . Это рассуждение применимо гораздо шире, чем .NET, но лучше объяснено в книге Framework Design Guidelines .
Основным аргументом в пользу предпочтения абстрактных базовых классов является управление версиями, потому что вы всегда можете добавить новый виртуальный член абстрактного базового класса без нарушения работы существующих клиентов. Это невозможно с интерфейсами.
Существуют сценарии, в которых интерфейс по-прежнему является правильным выбором (особенно когда вас не волнует управление версиями), но знание преимуществ и недостатков позволяет вам принять правильное решение.
] Итак, в качестве частичного ответа, прежде чем я продолжу: Наличие и интерфейса, и базового класса имеет смысл только в том случае, если вы решите изначально кодировать интерфейс. Если вы разрешаете интерфейс, вы должны кодировать только этот интерфейс, поскольку в противном случае вы нарушите принцип подстановки Лискова. Другими словами, даже если вы предоставляете базовый класс, реализующий интерфейс, вы не можете позволить своему коду использовать этот базовый класс.
Если вы решите кодировать базовый класс, наличие интерфейса не имеет смысла.
Если вы решаете написать код для интерфейса, наличие базового класса, обеспечивающего функции по умолчанию, необязательно. В этом нет необходимости, но это может ускорить работу разработчиков, поэтому вы можете предоставить его в качестве любезности.
Пример, который приходит на ум, - это ASP.NET MVC. Конвейер запросов работает на IController, но есть sa Базовый класс контроллера, который вы обычно используете для реализации поведения.
Окончательный ответ: Если вы используете абстрактный базовый класс, используйте только его. При использовании интерфейса базовый класс является необязательной любезностью для разработчиков.
Обновление: Я больше не предпочитаю абстрактные классы интерфейсам, и уже давно не предпочитаю; вместо этого я предпочитаю композицию наследованию, используя SOLID в качестве ориентира.
(Хотя я мог бы отредактировать приведенный выше текст напрямую, это радикально изменило бы характер сообщения, а поскольку некоторые люди сочли его достаточно ценным, чтобы обновить его). проголосуйте, я лучше оставлю исходный текст в силе и вместо этого добавлю это примечание. Последняя часть сообщения все еще имеет смысл, поэтому было бы стыдно удалить и ее.)
При использовании интерфейса базовый класс является необязательной любезностью для разработчиков.Обновление: Я больше не предпочитаю абстрактные классы интерфейсам, и уже давно не предпочитаю; вместо этого я предпочитаю композицию наследованию, используя SOLID в качестве ориентира.
(Хотя я мог бы редактировать приведенный выше текст напрямую, это радикально изменило бы характер сообщения, и поскольку некоторые люди сочли его достаточно ценным, чтобы обновить его). проголосуйте, я лучше оставлю исходный текст в силе и вместо этого добавлю это примечание. Последняя часть сообщения все еще имеет смысл, поэтому было бы стыдно удалить и ее.)
При использовании интерфейса базовый класс является необязательной любезностью для разработчиков.Обновление: Я больше не предпочитаю абстрактные классы интерфейсам, и уже давно не предпочитаю; вместо этого я предпочитаю композицию наследованию, используя SOLID в качестве ориентира.
(Хотя я мог бы отредактировать приведенный выше текст напрямую, это радикально изменило бы характер сообщения, а поскольку некоторые люди сочли его достаточно ценным, чтобы обновить его). проголосуйте, я лучше оставлю исходный текст в силе и вместо этого добавлю это примечание. Последняя часть сообщения все еще имеет смысл, поэтому было бы стыдно удалить и ее.)
Я обычно использую базовые классы (абстрактные или нет) для описания того, что есть , а интерфейсы я использую для описания возможностей объекта. .
Кот - это млекопитающее, но одна из его возможностей - это Pettable.
Или, говоря другими словами, классы - это существительные, а интерфейсы карта ближе к прилагательным.
Если вы хотите предоставить возможность полной замены вашей реализации, используйте интерфейс. Это особенно важно для взаимодействий между основными компонентами, они всегда должны быть разделены интерфейсами.
Также могут быть технические причины для предпочтения интерфейса, например, для включения имитации в модульных тестах.
Внутри компонента это может быть нормально использовать абстрактный класс напрямую для доступа к иерархии классов.
Если вы используете интерфейс и имеете иерархию реализующих классов, то рекомендуется иметь абстрактный класс, который содержит общие части реализации. Например,
interface Foo
abstract class FooBase implements Foo
class FunnyFoo extends FooBase
class SeriousFoo extends FooBase
Вы также можете иметь более абстрактные классы, наследующие друг от друга для более сложной иерархии.
Существует также так называемый DRY принцип - не повторяйся.
В вашем примере источников данных вы говорите, что существует некоторый общий код, который является общим для разных реализаций. Мне кажется, что лучший способ справиться с этим - иметь абстрактный класс с универсальным кодом в нем и некоторыми конкретными классами, расширяющими его.
Преимущество состоит в том, что каждое исправление ошибки в универсальном коде приносит пользу всем конкретным реализациям.
Если вы используете только интерфейс, вам придется поддерживать несколько копий одного и того же кода, который вызывает проблемы.
Что касается абстрактного интерфейса +, если нет немедленного оправдания для него, я бы не стал этого делать. Извлечение интерфейса из абстрактного класса - простой рефакторинг,
Я всегда использую эти рекомендации:
Правило доминирующей заботы диктует, что у класса всегда есть основная задача и 0 или более других (см. http://citeseer.ist.psu.edu/tarr99degrees.html ) . Эти 0 или более других вы затем реализуете через интерфейсы, поскольку класс затем реализует все типы, которые он должен реализовать (свой собственный и все интерфейсы, которые он реализует).
В мире множественного наследования реализаций (например, C ++ / Eiffel) можно наследовать от классов, реализующих интерфейсы. (Теоретически. На практике это может не работать так хорошо.)