자바스크립트 (Singleton, Factory, Chain, Interator) Pattern 구현



Singleton Pattern


함수클래스의 객체를 단 "하나"만 생성하게 만드는 디자인 패턴.


즉, 동일한 함수클래스 호출 시 반환되는 두번째 객체 부터는 이전에 생성된 객체를 반환하게 된다.


  1. var Singleton = (function () {
  2.  
  3.     var that = null;
  4.  
  5.     var Singleton = function () {
  6.  
  7.         if (that) return that;
  8.  
  9.         that = this;
  10.  
  11.         return that;
  12.     }
  13.  
  14.     return Singleton;
  15.  
  16. })();
  17.  
  18. function User() {
  19.     return this;
  20. }
  21.  
  22. var obj1 = Singleton();
  23. var obj2 = Singleton();
  24.  
  25. //alert(obj1 === obj2); // true
  26. //alert(new User() === new User()); // false





Factory Pattern


사용자가 구체적인 클래스 정보를 모르고도 빌드(객체 생성 캡슐화)를 통해 객체를 생성할 수 있도록 만드는 디자인 패턴.


아래 코드에서는 클래스 타입 뿐 아니라 해당 클래스의 매개변수까지 넘겨 객체를 반환할 수 있게 설계 되었다.


  1. var Factory = (function () {
  2.  
  3.     var Factory = function () {
  4.  
  5.         var ns = arguments[0].split('.')
  6.           , parent = eval(ns[0])
  7.           , childs = ns.slice(1);
  8.  
  9.         for (var i = 0, length = childs.length; i < length; i++) {
  10.  
  11.             if (!parent[childs[i]]) break;
  12.  
  13.             parent = parent[childs[i]];
  14.         }
  15.  
  16.         // parent.apply(obj, []) 함수의 반환값은 parent 함수(User)를 실행시킨 결과 return this(window object) 이다.
  17.         function T(args) { return parent.apply(this, Array.prototype.slice.call(args, 1)); };
  18.  
  19.         T.prototype = parent.prototype;
  20.  
  21.         return new T(arguments);
  22.     }
  23.  
  24.     return Factory;
  25.  
  26. })();
  27.  
  28.  
  29. function User(name, score) {
  30.     this.name = name;
  31.     this.score = score;
  32.    
  33.     return this;
  34. }
  35.  
  36. User.prototype.getName = function () {
  37.     return this.name;
  38. }
  39.  
  40. User.prototype.getScore = function () {
  41.     return this.score;
  42. }
  43.  
  44. User.name1 = function (name, score) {
  45.     this.name = name;
  46.     this.score = score;
  47.     return this;
  48. }
  49.  
  50. User.name1.prototype.getName = function () {
  51.     return this.name;
  52. }
  53.  
  54. User.name1.prototype.getScore = function () {
  55.     return this.score;
  56. }
  57.  
  58.  
  59. var obj1 = Factory('User', 'user1', 1);
  60. var obj2 = Factory('User.name1', 'user2', 2);
  61.  
  62. alert(obj1.getName());
  63. alert(obj1.getScore());
  64.  
  65. alert(obj2.getName());
  66. alert(obj2.getScore());





Chain Pattern


해당 객체를 메서드의 반환 값으로 지정하여 연속된 메서드를 호출할 수 있도록 만드는 디자인 패턴이다.


  1. var Chain = new (function () {
  2.  
  3.     var Chain = function () {
  4.  
  5.         this.name = '';
  6.         this.age = 0;
  7.  
  8.         return this;
  9.     };
  10.  
  11.     Chain.fn = Chain.prototype = {
  12.  
  13.         getName: function () {
  14.             return this.name;
  15.         },
  16.         setName: function (name) {
  17.             this.name = name;
  18.             return this;
  19.  
  20.         },
  21.         getAge: function () {
  22.             return this.age;
  23.         },
  24.         setAge: function (age) {
  25.             this.age = age;
  26.             return this;
  27.         }
  28.     };
  29.  
  30.     return Chain;
  31.  
  32. }())();
  33.  
  34. //alert(Chain.setName('test').getName()); // test
  35. //alert(Chain.setAge(10).getAge()); // 10
  36. //alert(Chain.setName('test').setAge(10).getAge()); // 10





Interator(반복자) Pattern


기능의 세부적인 구현을 외부로 노출시키지 않고, 컨테이너(Interator(arguments)의 요소에 차례대로 접근할 수 있는 방법(.each())을 제공하는 디자인 패턴


  1. var Interator = (function () {
  2.  
  3.     var Interator = function () {
  4.         return new Interator.fn.init(arguments);
  5.     };
  6.  
  7.     Interator.fn = Interator.prototype = {
  8.         init: function (arguments) {
  9.             this.arguments = arguments;
  10.             return this;
  11.         },
  12.         each: function (callback) {
  13.  
  14.             callback = typeof callback === 'function' ? callback : function () { ; };
  15.  
  16.             for (var i = 0, length = this.arguments.length; i < length; i++) {
  17.                
  18.                 var argument = this.arguments[i];
  19.                 callback.call(argument, i);
  20.             }
  21.         }
  22.     };
  23.  
  24.     Interator.fn.init.prototype = Interator.prototype;
  25.  
  26.     return Interator;
  27.  
  28. })();
  29.  
  30.  
  31. Interator(1, 2, 3).each(function (i) {
  32.     alert(this + ',' + i);
  33. });