Размещение всего кода модуля за 1 интерфейсом. Хорошая идея или нет? - PullRequest
1 голос
/ 09 декабря 2010

У меня есть несколько модулей (в основном C), которые необходимо переработать (используя C ++).В настоящее время основными проблемами являются:

  • многие части приложения зависят от функций модуля
  • некоторые части приложения могут захотеть отменить поведение модуля

Я думал о следующем подходе:

  • перепроектировать модуль так, чтобы он имел четкую современную структуру классов (используя интерфейсы, наследование, контейнеры STL, ...)
  • написание глобального класса интерфейса модуля, который можно использовать для доступа к любой функциональности модуля
  • написание реализации этого интерфейса, который просто отображает методы интерфейса на правильные методы правильного класса вinterface

Другие модули в приложении, которые в настоящее время непосредственно используют функции C модуля, должны быть переданы [реализация] этого интерфейса.Таким образом, если приложение хочет изменить поведение одной из функций модуля, оно просто наследует эту реализацию по умолчанию и отменяет любую функцию, которую оно хочет.

Пример:

  • Предположим, я полностью перепроектировал свой модуль так, чтобы у меня были такие классы, как: Book, Page, Cover, Author, ... Все эти классы имеют множество различных методов.
  • Я создаю глобальный интерфейс, называемый ILibraryAccessorс большим количеством чисто виртуальных методов
  • Я делаю реализацию по умолчанию, называемую DefaultLibraryAccessor, которая просто перенаправляет все методы в правильный метод правильного класса, например,
    • DefaultLibraryAccessor :: printBook (book)вызывает book-> print ()
    • DefaultLibraryAccessor :: getPage (book, 10) вызывает book-> getPage (10)
    • DefaultLibraryAccessor :: printPage (page) вызывает page-> print ()
  • Предположим, мое приложение имеет 3 вида окон
    • Первое позволяет использовать все функции и в качестве приложения.Ион Я хочу разрешить это
    • Второй также позволяет все функции (внутренне), но из приложения я хочу предотвратить печать отдельных страниц
    • Третий также позволяет все функции (внутренне), но из приложения я хочу запретить печать некоторых видов книг
  • При создании окна приложение передает реализацию ILibraryAccessor в окно
    • Первое окнополучит DefaultLibraryAccessor, разрешив все
    • Я передам специальный MyLibraryAccessor во второе окно, а в MyLibraryAccessor я отменю метод printPage и допустим сбой
    • Я передам специальный AnotherLibraryAccessorв третьем окне и в AnotherLibraryAccessor я отменю метод printBook и проверю тип книги, прежде чем вызову book-> print ().

Преимуществоэтот подход заключается в том, что, как показано в примере, приложение можетотменить любой метод, который он хочет отменить.Недостатком является то, что я получаю довольно большой интерфейс, и структура классов полностью теряется для всех модулей, которые хотят получить доступ к этому другому модулю.

Хорошая идея или нет?

Ответы [ 5 ]

4 голосов
/ 09 декабря 2010

Вы можете представить структуру класса с вложенными интерфейсами.Например, вместо DefaultLibraryAccessor::printBook(book), DefaultLibraryAccessor::Book::print(book).В противном случае это выглядит как хороший дизайн для меня.

2 голосов
/ 09 декабря 2010

ILibraryAccessor звучит как известный анти-паттерн, "класс бога".

Ваши отдельные окна, вероятно, лучше наследовать и переопределять на уровне книги / страницы / обложки / автора.

2 голосов
/ 09 декабря 2010

Может быть, посмотрите на шаблон дизайна под названием «Фасад».Используйте один фасад на модуль.Ваш подход кажется хорошим.

1 голос
/ 09 декабря 2010

Единственное, о чем я буду беспокоиться, это потеря детализации, частично рассмотренная ранее suszterpatt.Ваши реализации могут оказаться довольно тяжелыми и негибкими.Если вы уверены, что можете предсказать будущее использование модуля на этом этапе, то, вероятно, дизайн в порядке.

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

0 голосов
/ 09 декабря 2010

Если у вас есть n количество методов в вашем классе интерфейса, и есть m количество поведений для каждого метода, вы получите m*(nC1 + nC2 + nC3 + ... + nCn) Реализации вашего интерфейса (надеюсь, я правильно понял математику :)) , Сравните это с m*n реализациями, которые вам нужны, если бы у вас был один интерфейс для каждой функции. И этот метод добавил гибкость, что является более важным. Так что нет - я не думаю, что один интерфейс подойдет. Но вы не должны быть экстремальными.

РЕДАКТИРОВАТЬ: Я уверен, что математика не так. (

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...