В моих разработках я медленно перемещаюсь от объектно-ориентированного подхода до подхода интерфейсного основанного программирования. Более точно:
Простой пример разъясняет это.
В прошлом я записал эти классы:
Теперь я пишу эти классы:
Этот подход позволяет мне легко реализовывать классы насмешки для каждого из моих интерфейсов, и переключаться между старыми, более медленными реализациями и новыми, быстрыми внедрениями, и сравнивать их обоих в рамках того же приложения.
Для большинства случаев это работает очень хорошее, но это становится проблемой, если я хочу использовать итераторы для цикличного выполнения по наборам.
Предположим, что моя Библиотека имеет набор книг, и я хочу к итератору по ним. В прошлом это не было проблемой: Библиотека:: начните () и Библиотека:: конец () возвратил итератор (Библиотека:: итератор), на котором я мог легко записать цикл, как это:
for (Library::iterator it=myLibrary.begin();it!=mylibrary.end();++it) ...
Проблема состоит в том, что в основанном на интерфейсе подходе, нет никакой гарантии, что различные реализации ILibrary используют тот же вид итератора. Если, например, OldLibrary и NewLibrary оба наследовались ILibrary, то:
При требовании обоих, реализации ILibrary для возврата того же вида итератора не являются решением также, с тех пор на практике, инкрементная операция (++ это) должна быть реализована по-другому в обеих реализациях.
Это означает, что на практике я должен сделать итератор интерфейсом также, подразумевая, что приложение не может поместить итератор на стек (типичная проблема разрезания C++).
Я мог решить эту проблему путем обертывания интерфейса итератора в неинтерфейсном классе, но это кажется довольно сложным решением для того, что я пробую к obtian.
Там лучшие пути состоят в том, чтобы решить эту проблему?
Править: Некоторые разъяснения после комментариев сделаны Martin.
Предположим, что у меня есть класс, который возвращает все книги, отсортированные на популярности: LibraryBookFinder. Это имеет, начинаются () и конец () методы, которые возвращают LibraryBookFinder:: const_iterator, который обращается к книге.
Для замены моей старой реализации совершенно новой я хочу поместить старый LibraryBookFinder позади интерфейса ILibraryBookFinder и переименовать старую реализацию к OldSlowLibraryBookFinder.
Затем мое новое (образование пузырьков быстро) реализация под названием VeryFastCachingLibraryBookFinder может наследоваться ILibraryBookFinder. Это - то, куда проблема итератора возникает из.
Следующий шаг мог быть должен скрыть интерфейс позади фабрики, где я могу попросить, чтобы фабрика "дала мне 'средство поиска', которое очень хорошо в возврате книг согласно популярности, или согласно заголовку или автору.... Вы заканчиваете с кодом как это:
ILibraryBookFinder *myFinder = LibraryBookFinderFactory (FINDER_POPULARITY);
for (ILibraryBookFinder::const_iterator it=myFinder->begin();it!=myFinder.end();++it) ...
или если я хочу использовать другого критерии:
ILibraryBookFinder *myFinder = LibraryBookFinderFactory (FINDER_AUTHOR);
for (ILibraryBookFinder::const_iterator it=myFinder->begin();it!=myFinder.end();++it) ...
Аргумент LibraryBookFinderFactory может быть определен внешним фактором: параметр конфигурации, параметр командной строки, выбор в диалоговом окне... И каждая реализация имеет свой собственный вид оптимизации (например, автор книги не изменяется так, это может быть довольно статическим кэшем; популярность может ежедневно изменяться, который может подразумевать полностью другую структуру данных).