Хотя некоторые люди могут ненавидеть «дополнительные методы», они могут во многих случаях предлагать лучшую семантику, чем сильно разделенные интерфейсы. Среди прочего, они учитывают возможности того, что объект может получить способности или характеристики в течение своего времени жизни или что объект (особенно объект-обертка) может не знать, когда он сконструирован, о каких точных способностях он должен сообщать.
Хотя я вряд ли назову классы коллекций Java образцами хорошего дизайна, я бы предположил, что хорошая структура коллекций должна включать в себя большое количество дополнительных методов, а также способы расспросить коллекцию о ее характеристиках и возможностях . Такой дизайн позволит использовать один класс-обертку с большим разнообразием коллекций без случайного затенения способностей, которыми может обладать базовая коллекция. Если бы методы не были необязательными, то было бы необходимо иметь разные классы-оболочки для каждой комбинации функций, которые могут поддерживать коллекции, иначе в некоторых ситуациях некоторые оболочки могут быть непригодными.
Например, если коллекция поддерживает запись элемента по индексу или добавление элементов в конце, но не поддерживает вставку элементов в середине, тогда для кода, который хочет инкапсулировать его в оболочку, которая будет регистрировать все выполненные над ним действия, потребуется версия Оболочки журналирования, которая обеспечивала точную комбинацию поддерживаемых способностей, или, если ни одна из них не была доступна, пришлось бы использовать оболочку, которая поддерживала либо добавление, либо запись по индексу, но не оба. Если, однако, унифицированный интерфейс коллекции предоставил все три метода как «необязательные», но затем включил методы, чтобы указать, какой из дополнительных методов будет использоваться, то единственный класс-оболочка может обрабатывать коллекции, которые реализуют любую комбинацию функций. Когда его спросят, какие функции он поддерживает, оболочка может просто сообщить, что поддерживает инкапсулированная коллекция.
Обратите внимание, что существование «необязательных способностей» может в некоторых случаях позволять агрегированным коллекциям реализовывать определенные функции способами, которые были бы гораздо более эффективными, чем было бы возможно, если бы способности определялись существованием реализаций. Например, предположим, что concatenate
метод использовался для формирования составной коллекции из двух других, первым из которых оказался ArrayList с 1 000 000 элементов, а последним был набор из двадцати элементов, который можно было повторять только с самого начала. Если в составной коллекции запрашивается 1 000 013-й элемент (индекс 1 000 012), он может спросить у ArrayList, сколько элементов в нем содержится (т.е. 1 000 000), вычесть это из запрошенного индекса (получая 12), прочитать и пропустить двенадцать элементов из второго коллекция, а затем вернуть следующий элемент.
В такой ситуации, даже несмотря на то, что у составной коллекции не было бы мгновенного способа возврата элемента по индексу, запрос составной коллекции для 1 000 013-го элемента все равно был бы намного быстрее, чем чтение 1 000 013 элементов из нее по отдельности и игнорирование всех, кроме последнего один.