Вам бонус- начислено 1 монета за дневную активность. Сейчас у вас 1 монета

Приём программирования "Декоратор"

Лекция



Привет, сегодня поговорим про приём программирования "декоратор", обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое приём программирования "декоратор" , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).

"

  1. Пример декоратора
  2. Еще пример
  3. Зачем декораторы?
  4. Задачи

Декоратор — прием программирования, который позволяет взять существующую функцию и изменить/расширить ее поведение.

Декоратор получает функцию и возвращает обертку, которая модифицирует (декорирует) ее поведение, оставляя синтаксис вызова тем же.

Пример декоратора

Например, у нас есть функция sum(a,b):

function sum(a, b) {
  return a + b;
}

 

Создадим декоратор doublingDecorator, который меняет поведение, увеличивая результат работы функции в два раза:

 

01 function doublingDecorator(f) {        
02   return function() {
03     return 2*f.apply(this, arguments); // (*)
04   };
05 }
06  
07 // Использование:
08  
09 function sum(a, b) {
10   return a + b;
11 }
12  
13 sum = doublingDecorator(sum);
14  
15 alert( sum(1,2) ); // 6
16 alert( sum(2,3) ); // 10

 

Декоратор doublingDecorator создает анонимную функцию-обертку, которая в строке (*) вызывает fпри помощи apply с тем же контекстом this и аргументами arguments, а затем удваивает результат.

Этот декоратор можно применить два раза:

 

1 sum = doublingDecorator(sum);
2 sum = doublingDecorator(sum);
3  
4 alert( sum(1,2) ); // 12, т.е. 3 умножается на 4

 

Контекст this в sum никак не используется, поэтому можно бы было вызватьf.apply(null, arguments).

Еще пример

Посмотрим еще пример. Предположим, у нас есть функция isAdmin(), которая возвращает true, если у посетителя есть права администратора.

Можно создать универсальный декоратор, который добавляет в функцию проверку прав:

Например, создадим декоратор checkPermissionDecorator(f). Он будет возвращать обертку, которая передает вызов f в том случае, если у посетителя достаточно прав:

 

1 function checkPermissionDecorator(f) {
2   return function() {
3     if ( isAdmin() ) {
4       return f.apply(this, arguments);
5     }
6     alert('Недостаточно прав');
7   }
8 }
Использование декоратора:
1 function save() { ... }
2  
3 save = checkPermissionDecorator(save);
4 // Теперь вызов функции save() проверяет права

 

Декораторы можно использовать в любых комбинациях:

 

sum = checkPermissionDecorator(sum);
sum = doublingDecorator(sum);
// ...

 

Зачем декораторы?

Декораторы меняют поведение функции прозрачным образом.

  1. Декораторы можно повторно использовать. Об этом говорит сайт https://intellect.icu . Например, doublingDecorator можно применить не только к sum, но и к multiplydivide. Декоратор для проверки прав можно применить к любой функции.
  2. Несколько декораторов можно скомбинировать. Это придает дополнительную гибкость коду.

Примеры использования есть в задачах.

Задачи

 

Важность: 5

Создайте декоратор makeLogging(f, log), который берет функцию f и массив log.

Он должен возвращать обертку вокруг f, которая при каждом вызове записывает («логирует») аргументы в log, а затем передает вызов в f.

В этой задаче можно считать, что у функции f ровно один аргумент.

Работать должно так:

01 function work(a) {
02   /* ... */ // work - произвольная функция, один аргумент
03 }
04  
05 function makeLogging(f, log) { /* ваш код */ }
06  
07 var log = [];
08 work = makeLogging(work, log);
09  
10 work(1); // 1, добавлено в log
11 work(5); // 5, добавлено в log
12  
13 for(var i=0; i<log.length; i++) {
14   alert( 'Лог:' + log[i] ); // "Лог:1", затем "Лог:5"
15 }

 

Решение
[Открыть задачу в новом окне]

Важность: 3

Создайте декоратор makeLogging(func, log), для функции funcвозвращающий обертку, которая при каждом вызове добавляет ее аргументы в массив log.

Условие аналогично задаче Логирующий декоратор (1 аргумент), но допускается funcс любым набором аргументов.

Работать должно так:

01 function work(a, b) {
02   alert(a + b); // work - произвольная функция
03 }
04  
05 function makeLogging(f, log) { /* ваш код */ }
06  
07 var log = [];
08 work = makeLogging(work, log);
09  
10 work(1, 2); // 3
11 work(4, 5); // 9
12  
13 for(var i=0; i<log.length; i++) {
14   alert( 'Лог:' + [].join.call(log[i]) ); // "Лог:1,2", "Лог:4,5"
15 }

 

Решение

Решение аналогично задаче Логирующий декоратор (1 аргумент), разница в том, что в лог вместо одного аргумента идет весь объект arguments.

Для передачи вызова с произвольным количеством аргументов используемf.apply(this, arguments).

   
01 function work(a, b) {
02   alert(a + b); // work - произвольная функция
03 }
04  
05 function makeLogging(f, log) {
06   
07   function wrapper() {
08     log.push(arguments);
09     return f.apply(this, arguments);  
10   }
11  
12   return wrapper;
13 }
14  
15 var log = [];
16 work = makeLogging(work, log);
17  
18 work(1, 2); // 3
19 work(4, 5); // 9
20  
21 for(var i=0; i<log.length; i++) {
22   alert( 'Лог:' + [].join.call(log[i]) ); // "Лог:1,2", "Лог:4,5"
23 }

 

[Открыть задачу в новом окне]

Важность: 5

Создайте декоратор makeCaching(f), который берет функцию f и возвращает обертку, которая кеширует ее результаты.

В этой задаче функция f имеет только один аргумент, и он является числом.

  1. При первом вызове обертки с определенным аргументом — она вызывает f и запоминает значение.
  2. При втором и последующих вызовах с тем же аргументом возвращается запомненное значение.

Должно работать так:

01 function f(arg) {
02   return Math.random()*arg; // может быть любой функцией
03 }
04  
05 function makeCaching(f) { /* ваш код */ }
06  
07 f = makeCaching(f);
08  
09 var a, b;
10  
11 a = f(1);
12 b = f(1);
13 alert( a == b ); // true (значение закешировано)
14  
15 b = f(2);
16 alert( a == b ); // false, другой аргумент => другое значение

 

Решение

Запоминать результаты вызова функции будем в замыкании, в объектеcache: { ключ:значение }.

 

   
01 function f(x) {
02   return Math.random()*x;
03 }
04  
05 function makeCaching(f) {
06   var cache = {}; 
07  
08   return function(x) {
09     if (!(x in cache)) {  
10       cache[x] = f.call(this, x);
11     }
12     return cache[x];
13   };
14  
15 }
16  
17 f = makeCaching(f);
18  
19 var a = f(1);
20 var b = f(1);
21 alert( a == b ); // true (значение закешировано)
22  
23 b = f(2);
24 alert( a == b ); // false, другой аргумент => другое значение

 

Обратите внимание: проверка на наличие уже подсчитанного значения выглядит так:if (x in cache). Менее универсально можно проверить так: if (cache[x]), это если мы точно знаем, что cache[x] никогда не будет false0 и т.п.

К сожалению, в одной статье не просто дать все знания про приём программирования "декоратор". Но я - старался. Если ты проявишь интерес к раскрытию подробностей,я обязательно напишу продолжение! Надеюсь, что теперь ты понял что такое приём программирования "декоратор" и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)

Из статьи мы узнали кратко, но содержательно про приём программирования "декоратор"
создано: 2014-10-07
обновлено: 2021-03-13
132590



Рейтиг 9 of 10. count vote: 2
Вы довольны ?:


Поделиться:

Найди готовое или заработай

С нашими удобными сервисами без комиссии*

Как это работает? | Узнать цену?

Найти исполнителя
$0 / весь год.
  • У вас есть задание, но нет времени его делать
  • Вы хотите найти профессионала для выплнения задания
  • Возможно примерение функции гаранта на сделку
  • Приорететная поддержка
  • идеально подходит для студентов, у которых нет времени для решения заданий
Готовое решение
$0 / весь год.
  • Вы можите продать(исполнителем) или купить(заказчиком) готовое решение
  • Вам предоставят готовое решение
  • Будет предоставлено в минимальные сроки т.к. задание уже готовое
  • Вы получите базовую гарантию 8 дней
  • Вы можете заработать на материалах
  • подходит как для студентов так и для преподавателей
Я исполнитель
$0 / весь год.
  • Вы профессионал своего дела
  • У вас есть опыт и желание зарабатывать
  • Вы хотите помочь в решении задач или написании работ
  • Возможно примерение функции гаранта на сделку
  • подходит для опытных студентов так и для преподавателей



Комментарии


Оставить комментарий
Если у вас есть какое-либо предложение, идея, благодарность или комментарий, не стесняйтесь писать. Мы очень ценим отзывы и рады услышать ваше мнение.
To reply

Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)

Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)