Книга: 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); }
  }

Одно из преимуществ применения приема композиции в данном случае заключается в том, что требуется определить только один подкласс FilteredSet. Экземпляры этого класса могут накладывать ограничения на элементы любого другого эк» земпляра множества. Например, вместо класса NonNullSet, представленного выше, реализовать подобные ограничения можно было бы так:

var s = new FilteredSet(new Set(), function(x) { return x !== null; });

Можно даже наложить еще один фильтр на фильтрованное множество:

var t = new FilteredSet(s, { function(x) { return !(x instanceof Set); });

Оглавление книги


Генерация: 0.597. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз