Принцип подстановки Лискова в принципе не позволяет вам чрезмерно использовать наследование реализации: вы никогда не должны использовать наследование только для повторного использования кода (для этого есть состав)! Придерживаясь LSP, вы можете быть уверены, что между вашим суперклассом и вашим подклассом действительно существуют отношения «есть отношения».
Это говорит о том, что ваши подклассы должны реализовывать все методы подкласса аналогично реализации методов в подклассе. Вы никогда не должны переопределять метод с реализацией NOP или возвращать нуль, когда супертип генерирует исключение; указанные в Условиях проектирования по контракту, вы должны соблюдать контракт метода из суперкласса при переопределении метода. Способ защиты от нарушения этого принципа состоит в том, чтобы никогда не отменять реализованный метод; вместо этого извлеките интерфейс и реализуйте этот интерфейс в обоих классах.
Принцип разделения интерфейсов, принцип единой ответственности и принцип высокого сцепления от GRASP так или иначе связаны между собой; они ссылаются на тот факт, что организация должна нести ответственность только за одну вещь, так что есть только одна причина для изменения, чтобы изменение было сделано очень легко.
Это фактически говорит о том, что если класс реализует интерфейс, то он должен реализовать и использовать все методы этого интерфейса. Если есть методы, которые не нужны в этом конкретном классе, то интерфейс не годится и должен быть разбит на два интерфейса, в котором есть только методы, необходимые исходному классу. Это может быть рассмотрено из POV, который относится к предыдущему принципу тем, что он не позволяет создавать большие интерфейсы, чтобы их реализация могла нарушить LSP.
Вы можете видеть Инверсию Зависимости в Заводском Образце; здесь и компонент высокого уровня (клиент), и компонент низкого уровня (отдельный экземпляр, который будет создан) зависят от абстракции(интерфейс). Способ применить его в многоуровневой архитектуре: вы не должны определять интерфейс для слоя в слое, который реализован, а в вызываемом модуле. Например, API для уровня источника данных должен быть записан не на уровне источника данных, а на уровне логики бизнеса, где он должен быть вызван. Таким образом, уровень источника данных наследует / зависит от поведения, определенного в бизнес-логике (таким образом, инверсия), а не наоборот (как было бы в обычном порядке). Это обеспечивает гибкость проектирования, позволяя бизнес-логике работать без каких-либо изменений кода с другим совершенно другим источником данных.