Decorator pattern allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. Real world uses can be many, some of them are:

  • Extending a third party service to suit your needs
  • Cross cutting concerns like logging can be easily incorporated

Consider a simple example, where you have a service called greeting, and that has a method called sayHi.
Now if you want to modify the behavior of the sayHi method and want to add some more methods to the existing service you can easily accomplish it using $provide.decorator.
View it in Plunker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJS Form Example</title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
    <script type="text/javascript">
        var app = angular.module('myApp', []);
        app.config(function ($provide) {
            $provide.decorator('greeting', function ($delegate) {
                //saving the original sayHi method into a variable
                var sayHi = $delegate.sayHi;
 
                //adding a new method to greeting service
                $delegate.sayHello = function (name) {
                    return sayHi(name).replace('Hi', 'Hello');
                };
 
                //decorating(converting to uppercase) the original sayHi method with our new functionality
                $delegate.sayHi = function (name) {
                    return sayHi(name).toUpperCase();
                    //or can invoke like the following
                    // sayHi.apply(null, arguments).toUpperCase();
                };
                return $delegate;
            });
        });
        app.factory('greeting', function () {
            return {
                sayHi: function (name) {
                    return 'Hi ' + name;
                }
            };
        });
        app.controller('myCtrl', function ($scope, greeting) {
            var vm = this;
            vm.greet = function () {
                vm.msg = greeting.sayHi(vm.name);
                vm.decMsg = greeting.sayHello(vm.name);
            }
        });
    </script>
</head>
 
<body ng-controller="myCtrl as ctrl">
    <input type="text" ng-model="ctrl.name" />
    <input type="button" value="Greet" ng-click="ctrl.greet()" />
    <br/>This should be in caps:{{ctrl.msg}}
    <br/>This is not in caps:{{ctrl.decMsg}}
</body>
 
</html>
“Keep learning.”
-Rushi

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>