2013-08-25 11 views
3

DIP-состояния:В чем разница между принципом Open/Closed и принципом инверсии зависимостей?

  • модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
  • Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

И OCP гласит:

Программные объекты (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации.

Я думаю, что если мы удовлетворим DIP, он также будет охватывать OCP. Итак, почему мы разделяем эти два принципа?

+0

'OCP' от' SOLID', который по-прежнему спорный о реальной архитектуре. Вы можете найти хорошую статью от Джона Скита здесь http://msmvps.com/blogs/jon_skeet/archive/2013/03/15/the-open-closed-principle-in-review.aspx – Fendy

ответ

4

Я думаю, что соблюдение принципа DIP упрощает выполнение принципа OCP. Однако никто не гарантирует другого.

Например, я могу создать класс, который имеет метод, который принимает параметр Base. Если base является абстрактным классом, то я придерживаюсь DIP, поскольку я инвертировал зависимость от вызывающего. Однако, если код в этом методе делает что-то вроде:

if (base is derived) 
    (derived)base.DoSomethingSpecificToDerived; 
elsif (base is evenMoreDerived) 
    (evenMoreDerived)base.DoSomethingSpecificToEvenMoreDerived; 

Тогда это не OCP соответствует, как я должен изменить его каждый раз, когда я добавить новую производную.

Это очень надуманный пример, но вы поняли мою точку зрения.

+2

Но в вашем примере High (что ваши коды в нем), зависит от реализаций низкого уровня (полученных, evenMoreDerived), поэтому ваш образец также нарушает DIP, я думаю. – Masoud

+0

Это правда. Тем не менее, мое понимание DIP заключается в том, что вы инвертируете управление зависимостями на более высокий уровень, который имеет этот класс. Как я уже сказал, это очень надуманный пример. –

5

DIP сообщает вам , как для организации зависимостей. Он не сообщает вам , когда вы сделали с определенным интерфейсом.

Грубо говоря, сообщение OCP должно содержать полные, но минималистические интерфейсы. Другими словами, он сообщает вам , когда вы закончили с интерфейсом, но он не говорит вам , как для этого.

В некотором смысле DIP и OCP являются ортогональными.


Итак, почему мы разделить эти два принципа?

Что касается дизайна моделей и названных принципов, почти все они имеют общее:

  1. Найди то, что изменяется и инкапсулировать (скрыть) его.

  2. Предпочитают агрегацию над наследованием.

  3. Дизайн интерфейсов.

Даже если названные закономерности и принципы частично перекрываются в каком-то смысле, они говорят вам что-то более конкретное (в более конкретной ситуации), чем выше трех общих принципов.

0

OCP делает зависимый класс легко потребляемым. OCP позволяет асинхронное потребление интерфейса путем развязки старых реализаций из более новых версий. Это позволяет тем, что от него зависит, продолжать зависеть от него даже перед лицом изменений для других целей. Таким образом, класс никогда не должен заботиться о том, кто его называет.

DIP делает пару вещей. Это упрощает работу в зависимости от внешних классов. Инъекция зависимостей позволяет замену зависимостей путем поощрения разделения обязанностей на создание от потребления. Вместо того, чтобы создавать внешнюю зависимость, которая должна потребляться, шаблон указывает, что он должен быть предоставлен извне. В конечном итоге это поощряет код, который является идемпотентным (код, который не меняет внешнее состояние). Идемпотентный код хорош, потому что можно проверить, что он делает только то, что сразу видно. У него нет внешних побочных эффектов. Это очень легко проверяемое, понятное и читаемое.