| « Неожиданные сюрпризы плеера 9.0.28 | Интерфейсы в actionscript 2.0. Часть 2. Одинаковое поведение - разная реализация » |
Интерфейсы в actionscript 2.0. Часть 3. Много – лучше, чем один
В конце прошлой части я затронула вопрос о том, что есть смысл избегать использования интерфейсов, включающих в себя много различных и не связанных друг с другом методов. Использование таких раздутых интерфейсов может иметь далеко идущие последствия. Помимо появления объектов с пустыми методами (см. часть 2), некоторые идеологические несовершенства со временем могут привести к практическим сложностям.
Приведем пример ‘неправильного’ интерфейса, чтобы было понятно, о чем речь. Пусть у нас есть графический редактор. Будем использовать интерфейс IEditableObject для однообразного общения системы с элементами (линия, текст, картинка, видео и т. п).
- /**
- * Редактируемый объект.
- * @author J.Nikolaeva
- * @version 22.01.2007
- */
- interface IEditableObject {
- /**
- * Ширина объекта.
- * @return ничего
- */
- public function getWidth():Void;
- /**
- * Высота объекта.
- * @return ничего
- */
- public function getHeight():Void;
- /**
- * Установка размеров.
- * @param w ширина
- * @param h высота
- * @return ничего
- */
- public function setSize(w:Number, h:Number):Void;
- /**
- * Установка цвета.
- * @param color цвет
- * @return ничего
- */
- public function setColor(color:Number):Void;
- /**
- * Цвет объекта.
- * @param
- * @return
- */
- public function getColor():Void;
- /**
- * Обновление вида объекта, после изменения соответствующих данных.
- * @return ничего
- */
- public function update():Void;
- /**
- * Создает полную копию объекта.
- * @return копия объекта
- */
- public function clone():IEditableObject;
- }
Все, кто имеет дело с объектами типа IEditableObject, будут в курсе ‘личной жизни’ этих объектов - у них есть и цвет, и размер, и более того, они могут обновляться после каких-то изменений и даже производить своих клонов. Вряд ли все описанные методы могут быть использованы каким-то модулем одновременно. Использование интерфейса типа IEditableObject, говорит о растущей вероятности того, что принцип низкой связанности и высокого зацепления в приложении не сможет выполняться.
Вместо того, чтобы интерфейс сообщал о конкретных, необходимых определенному модулю, возможностях, он будет пытаться объять необъятное - сообщить всем модулям обо всех своих возможностях. А ведь в идеале, каждый модуль должен ‘видеть’ только ‘свои’ методы, то есть методы, которые он будет реально использовать.
Особенно такие откровенные интерфейсы неудобны при командной разработке, когда не все участники процесса должны знать о таких опасных возможностях как создание клонов. А со временем, в интерфейс будут добавляться все новые и новые методы, в ворохе которых смогут разобраться только самые усидчивые и терпеливые разработчики. А главное, будет уже совсем не понятно, что именно могут экземпляры этого интерфейса.
Как избежать выше описанных проблем и не разувериться в возможностях применения интерфейсов?
Можно ‘разделить’ интерфейс IEditableObject на несколько более удобных интерфейсов: IResizable, IСolorChangeable, IDataDependent, ICloneable. Теперь видно, какое поведение определяется каждым интерфейсом.
Вот пример кода, иллюстрирующий использование новых интерфейсов.
- /**
- * Контроллер всего графического редактора.
- * @author J.Nikolaeva
- * @version 22.01.2007
- */
- class EditorController {
- private var archive:CopiesArchive;
- /**
- * Конструктор.
- */
- public function EditorController() {
- archive = new CopiesArchive();
- }
- public function addLine():Void {
- var line:Line = ElementsFactory.createLine();
- archive.addElement(line);
- }
- }
- /**
- * Линия.
- * @author J.Nikolaeva
- * @version 23.01.2007
- */
- class Line implements IResizable, IColorChangeable, IDataDependent, ICloneable {...}
- /**
- * Архив копий объектов.
- * @author J.Nikolaeva
- * @version 23.01.2007
- */
- class CopiesArchive {
- /**
- * Конструктор.
- */
- public function CopiesArchive() {
- }
- public function addElement(element:ICloneable):Void {
- }
- }
Рассмотрим метод addLine в классе EditorController. Видно, что несмотря на то, что мы получаем от ElementsFactory соврешенно конкретный элемент типа Line, класс CopiesArchive ‘знает’ объект только по интерфейсу ICloneable, то есть знает только то, что этот элемент имеет метод clone. Таким образом мы сможем помещать в архив любые элементы реализующие интерфейс ICloneable, даже если это вообще не элемент редактора, а какая-то другая сущность. А это было бы невозможно при использовании интерфейса IEditableObject.
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
3 комментариев
Аналогично.
а зачем на каждый класс по интерфейсу?
Я вроде бы не писала, что каждому классу надо по интерфейсу.