Java: Как сделать защитную копию, когда у вас есть только интерфейс - PullRequest
4 голосов
/ 22 сентября 2009

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

Например, если у меня есть объект, который принимает реализацию FilenameFilter в своем конструкторе, как я могу сделать его защитную копию, когда все, что я о нем знаю, это то, что он реализует FilenameFilter? Должен ли я прибегнуть к использованию отражения?

Ответы [ 3 ]

6 голосов
/ 22 сентября 2009

Лучшая ставка при решении подобных проблем - сделать как можно больше неизменяемых объектов, то есть их нельзя изменить после создания. Если вам нужно изменить их, вы создаете новый, оставляя оригинал нетронутым.

Это также лучше для многопоточности.

Изменяемые объекты, как правило, не считаются «лучшей практикой». Вы не можете полностью устранить их, но, как говорит Джош Блох, предпочитаете неизменность.

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

2 голосов
/ 22 сентября 2009

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

Ваш прекрасный пример. FilenameFilter является неизменным - ничто не может изменить его через этот интерфейс. Не стесняйтесь передавать его по желанию. Единственная потенциальная проблема - это многопоточность, и это довольно редко.

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

Вы заметите, что JDK почти никогда не передает коллекции. Это специально, и точную причину для шаблона «Копирование» вы рассматриваете. Обычно JDK передает массив, и большинство коллекций имеют довольно простой способ создания копии своего содержимого для передачи.

Копирование объекта на самом деле встречается крайне редко - коллекции и массивы являются основными, о которых нужно заботиться. Большинство других объектов могут защитить себя довольно хорошо, если они даже наполовину прилично спроектированы.

0 голосов
/ 22 сентября 2009

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

Тогда, предполагая, что копия строго необходима, я бы определил подинтерфейс FileFilter, который определяет метод копирования с соответствующей семантикой. Используйте этот интерфейс вместо FileFilter в упомянутом конструкторе, передайте FileFilters, которые реализуют интерфейс, и организуйте, чтобы вышеупомянутый конструктор вызывал метод copy в соответствующее время.

(В качестве альтернативы вы можете использовать Object.clone() в зависимости от структуры пакета вашего приложения.)

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