Книга: JavaScript. Подробное руководство, 6-е издание
9.7.3. Композиция в сравнении с наследованием
9.7.3. Композиция в сравнении с наследованием
В предыдущем разделе мы решили определить класс множеств, накладывающий ограничения на свои элементы в соответствии с некоторыми критериями, а для достижения поставленной цели использовали механизм наследования, определив функцию создания специализированного подкласса указанной реализации множества, использующего указанную функцию-фильтр для ограничения круга допустимых элементов множества. При таком подходе для каждой комбинации суперкласса и функции-фильтра необходимо создавать новый класс.
Однако существует более простой путь решения этой задачи. В объектно-ориентированном программировании существует известный принцип «предпочтения композиции перед наследованием».[18]
В данном случае применение приема композиции могло бы выглядеть как реализация нового множества, «обертывающего» другой объект множества и делегирующего ему все обращения после фильтрации нежелательных элементов. Пример 9.15 демонстрирует, как это реализовать.
Пример 9.15. Композиция множеств вместо наследования
/*
* Объект FilteredSet обертывает указанный объект множества и применяет
* указанный фильтр в своем методе add(). Обращения ко всем остальным базовым
* методам просто передаются обернутому экземпляру множества.
*/
var FilteredSet = Set.extend(
function FilteredSet(set, filter) { // Конструктор
this.set = set; this.filter = filter;
},
{ // Методы экземпляров
add: function() {
// Если фильтр был указан, применить его
if (this.filter) {
for(var і = 0; і < arguments.length; i++) {
var v = arguments[i];
if (!this.filter(v))
throw new Error("FilteredSet: значение " + v + " отвергнуто фильтром");
}
}
// Затем вызвать метод add() объекта
this.set.add() this.set.add.apply(this.set, arguments);
return this;
},
// Остальные методы просто вызывают соответствующие
// методы объекта this.set и ничего более,
remove: function() {
this.set.remove.apply(this.set, arguments);
return this;
}.
contains: function(v) {return this.set.contains(v);},
size: function() { return this.set.size(); },
foreach: function(f,c) { this.set.foreach(f.c); }
}
Одно из преимуществ применения приема композиции в данном случае заключается в том, что требуется определить только один подкласс FilteredSe
t. Экземпляры этого класса могут накладывать ограничения на элементы любого другого эк» земпляра множества. Например, вместо класса NonNullSet
, представленного выше, реализовать подобные ограничения можно было бы так:
var s = new FilteredSet(new Set(), function(x) { return x !== null; });
Можно даже наложить еще один фильтр на фильтрованное множество:
var t = new FilteredSet(s, { function(x) { return !(x instanceof Set); });
- 9.7. Подклассы
- 5. Композиция
- Двоичная композиция
- Динамический в сравнении со статическим SQL
- Заключительное слово: «4Р» в сравнении с «4С»
- Ядро Linux в сравнении с классическими ядрами Unix
- Глава 10 Композиция
- Приложение J. Различия в поведении при попарном сравнении
- Функциональная декомпозиция
- Декомпозиция
- Модульная Композиция
- Декомпозиция, основанная на объектах