<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Javascript OOP框架YOOP重構實踐(下)

      繼續重構

      提取基類Structure

      增加測試

      describe("測試AClass", function () {
          it("子類全部實現抽象父類的抽象成員時,不拋出異常", function () {
              var A = YYC.AClass({
                  Init: function (t) {
                      this.a = t;
                      this.b = 2;
                  },
                  Public: {
                      p: function () {
                          return 0;
                      }
                  },
                  Private: {
                      _m: 1
                  },
                  Protected: {
                      P_h: function () {
                          return this._m;
                      },
                      P_k: 3
                  },
                  Abstract: {
                      move: function () { },
                      u: 0,
                      t: function () { }
                  }
              });
              var B = YYC.Class(A, {
                  Init: function () {
                      this.b = 100;
                      this.base(200);
                  },
                  Public: {
                      move: function () {
                          return this.P_h();
                      },
                      t: function () { },
                      u: 20
                  }
              });
              var C = YYC.Class(B, {
                  Public: {
                      move: function () {
                          var baseResult = this.base();
      
                          return baseResult;
                      },
                      t: function () { }
                  }
              });
      
              var b = new B();
              var c = new C();
      
              expect([b.a, b.b]).toEqual([200, 2]);
              expect([b.p(), b.move(), b.u]).toEqual([0, 1, 20]);
              expect(c.move()).toEqual(1);
          });
      });
      
      describe("測試Interface", function () {
          it("子類沒有全部實現了接口方法和屬性,拋出異常", function () {
              var Int = YYC.Interface("A", "B");
      
              expect(function () {
                  YYC.AClass({ Interface: Int }, {
                      Public: {
                          B: function () { }
                      }
                  });
              }).toThrow();
      
              var Int2 = YYC.Interface(Int, ["C"], ["a"]);
      
              expect(function () {
                  YYC.AClass({ Interface: Int2 }, {
                      Public: {
                          A: function () { },
                          B: function () { },
                          C: function () { }
                      }
                  });
              }).toThrow();
              expect(function () {
                  YYC.AClass({ Interface: Int2 }, {
                      Public: {
                          B: function () { },
                          C: function () { },
                          a: 1
                      }
                  });
              }).toThrow();
          });
      });
      View Code

      通過重構實踐(一)的重構,我發現AClass和Class有很多相似之處,因此啟發我采用oo思想來重構,提取出AClass和Class的基類Structure,將兩者的共同或相似的代碼放到Structure中,然后在Structure中運用模板模式,調用子類實現的方法或屬性(如P_class、P_prepareCheck)。

      另外進行上面的重構后,可以減少一些方法的形參個數,因為這些形參可以在方法內部通過this來獲得了。

      如_addStatic重構前:

      function _addStatic(_class, prop) {
          var Static = null;
          var k = null;
      
          Static = prop.Static ? prop.Static : null;
          //靜態屬性/方法賦值
          for (k in Static) {
              _class[k] = Static[k];
          }
      };

      重構后(_addStatic移到Structure中,并改名為P_addStatic,表示為保護方法):

      this.P_addStatic = function () {
          var Static = null,
              k = null,
              _class = this.P_class,
              prop = this.prop;
      
          Static = prop.Static ? prop.Static : null;
          //靜態屬性/方法賦值
          for (k in Static) {
              _class[k] = Static[k];
          }
      };

      然后又進行了一些小的重構(如刪除密封方法的判斷、檢查;將AClass、Class中調用成員的職責提取為buildAClass、buildClass;重命名addPublic為prepareAndAddPublic等),重構后結構A2(包括Structure、AClass、Class)為:

      (function () {
      
          function Structure() {
              this.parentClass = null;
              this.interface = null;
              this.prop = null;
      
              /* 深拷貝
          */
              this.P_extendDeep = function (parent, child) {
                  var i = null,
                  len = 0,
                        toStr = Object.prototype.toString,
                        sArr = "[object Array]",
                        sOb = "[object Object]",
                        type = "",
                 _child = null;
      
                  //數組的話,不獲得Array原型上的成員。
                  if (toStr.call(parent) === sArr) {
                      _child = child || [];
      
                      for (i = 0, len = parent.length; i < len; i++) {
                          type = toStr.call(parent[i]);
                          if (type === sArr || type === sOb) {    //如果為數組或object對象
                              _child[i] = type === sArr ? [] : {};
                              arguments.callee(parent[i], _child[i]);
                          } else {
                              _child[i] = parent[i];
                          }
                      }
                  }
                      //對象的話,要獲得原型鏈上的成員。因為考慮以下情景:
                      //類A繼承于類B,現在想要拷貝類A的實例a的成員(包括從類B繼承來的成員),那么就需要獲得原型鏈上的成員。
                  else if (toStr.call(parent) === sOb) {
                      _child = child || {};
      
                      for (i in parent) {
                          type = toStr.call(parent[i]);
                          if (type === sArr || type === sOb) {
                              _child[i] = type === sArr ? [] : {};
                              arguments.callee(parent[i], _child[i]);
                          } else {
                              _child[i] = parent[i];
                          }
                      }
                  }
                  else {
                      _child = parent;
                  }
      
      
                  return _child;
              };
              //檢查子類的公有方法+虛方法+抽象方法是否包含父類的抽象方法/屬性 或 接口方法/屬性。
              //不用hasOwnProperty判斷!否則就檢查不到是否包含了父類的抽象方法/屬性 或 接口方法/屬性。
              this.P_check = function (parentClass) {
                  //var parentClass = this.parentClass,
                  var interface = this.interface,
                      children = this.children;
      
                  if (parentClass) {
                      _checkAbstract(parentClass, children);
                  }
                  else if (interface) {
                      _checkInterface(interface, children);
                  }
              };
              function _checkAbstract(parentClass, children) {
                  var name = "";
      
                  //檢查是否實現了抽象方法/屬性
                  for (name in parentClass.prototype) {
                      if (parentClass.prototype.hasOwnProperty(name)) {
                          if (name === "constructor") {
                              continue;
                          }
                          if (name.contain("Abstract_")) {
                              //抽象方法
                              if (typeof parentClass.prototype[name] === "function") {
                                  if (_noMethodForAbstract(children, name) && _noMethodForAbstract(parentClass.prototype, name)) {
                                      throw new Error("Abstract method '" + name + "' must be overwrited!");
                                  }
                              }
                                  //抽象屬性
                              else {
                                  if (_noAttritubeForAbstract(children, name) && _noAttritubeForAbstract(parentClass.prototype, name)) {
                                      throw new Error("Abstract attribute '" + name + "' must be overwrited!");
                                  }
                              }
                          }
                      }
                  }
              };
              function _checkInterface(interface, children) {
                  var name = "";
      
                  //檢查是否實現了接口方法/屬性
                  for (name in interface.prototype) {
                      if (name === "constructor") {
                          continue;
                      }
                      //接口方法
                      if (typeof interface.prototype[name] === "function") {
                          if (_noMethodForInterface(children, name) && _noMethodForInterface(parentClass.prototype, name)) {
                              throw new Error("Interface method '" + name + "' must be overwrited!");
                          }
                      }
                          //接口屬性
                      else {
                          if (_noAttritubeForInterface(children, name) && _noAttritubeForInterface(parentClass.prototype, name)) {
                              throw new Error("Interface attribute '" + name + "' must be overwrited!");
                          }
                      }
                  }
              };
      
              function _noMethodForAbstract(_class, name) {
                  return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] !== "function";
              };
              function _noAttritubeForAbstract(_class, name) {
                  return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] === "function";
              };
              function _noMethodForInterface(_class, name) {
                  return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] !== "function";
              };
              function _noAttritubeForInterface(_class, name) {
                  return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] === "function";
              };
      
              //檢查抽象成員
              this.P_addAbstract = function (abstract) {
                  var name = "",
                      currentClass = this.P_class;
      
                  for (name in abstract) {
                      if (abstract.hasOwnProperty(name)) {
                          //抽象方法前面加"Abstract_"前綴
                          currentClass.prototype["Abstract_" + name] = abstract[name];
                          //temp[name] = abstract[name];    //加入temp
                      }
                  }
              };
      
              //檢查虛方法(不能為虛屬性)
              this.P_addVirtual = function (virtual) {
                  var name = "",
                      currentClass = this.P_class;
      
                  for (name in virtual) {
                      if (virtual.hasOwnProperty(name)) {
                          if (typeof virtual[name] !== "function") {
                              throw new Error("Virtual attribute is not allowed!");
                          }
                          else {
                              currentClass.prototype[name] = virtual[name];
                              //temp[name] = virtual[name];    //加入this.temp
                          }
                      }
                  }
              };
      
              ////加入密封方法。
              ////沒有實現檢查子類是否重寫了父類的密封方法,只是定義了一個規范。
              //this.P_addSealed = function (sealed, currentClass) {
              //    var name = "";
      
              //    for (name in sealed) {
              //        if (sealed.hasOwnProperty(name)) {
              //            currentClass.prototype[name] = sealed[name];
              //            //temp[name] = sealed[name];    //加入this.temp
              //        }
              //    }
              //};
      
              //獲得在原型prototype中不存在同名的str。
              //如果有同名,則加上前綴"_"
              this.P_getNoRepeatStrInPrototype = function (prototype, str) {
                  var new_str = "";
      
                  if (!prototype[str]) {
                      return str;
                  }
                  new_str = "_" + str;
      
                  return arguments.callee(prototype, new_str);
              };
              this.P_addStatic = function () {
                  var Static = null,
                      k = null,
                      _class = this.P_class,
                      prop = this.prop;
      
                  Static = prop.Static ? prop.Static : null;
                  //靜態屬性/方法賦值
                  for (k in Static) {
                      _class[k] = Static[k];
                  }
              };
      
              this.P_inherit = function () {
                  var _class = this.P_class,
                      parentClass = this.parentClass;
      
                  _class.prototype = this.P_extendDeep(parentClass.prototype);
                  _class.prototype.constructor = _class;
      
                  // 如果父類存在,則實例對象的baseClass指向父類的原型。
                  // 這就提供了在實例對象中調用父類方法的途徑。
                  //baseClass的方法是指向this.parentClass的,不是指向F(子類)的!
                  _class.prototype[this.P_getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;
              };
              this.P_addInit = function () {
                  //var self = this;
                  var _class = this.P_class,
                      parentClass = this.parentClass,
                      prop = this.prop;
      
                  if (prop.Init) {
                      // 如果此類繼承自父類this.parent并且父類原型中存在同名函數name
                      if (parentClass &&
              typeof prop.Init === "function" &&
              typeof _class.prototype.Init === "function") {
                          //if (this.parentClass) {
                          _class.prototype.Init = function (name) {
                              return function () {
                                  /*
                                  //此處不用創建閉包了!因為外面已經創建了閉包,name已經被保存了!
                                  this.baseToParrent = function () {
                                      //這個寫法也可以!為什么不用apply修正this也行??!
                                      //this.parentClass.prototype[name](); 
              
                                      //此處的arguments為baseToParrent方法傳入的形參
                                      //注意!要加上“return”,這樣才能返回this.parentClass.prototype[name]的返回值
                                      return this.parentClass.prototype[name].apply(this.parentClass.prototype, arguments);
                                  };
                                  */
                                  //指向子類,可以用于模版模式
                                  this.base = parentClass.prototype[name];
      
                                  //執行fn并返回執行的結果
                                  //此處的arguments為F.prototype[name]方法傳入的形參。
                                  return prop[name].apply(this, arguments);
                              };
      
                          }("Init");
                      }
                      else {
                          _class.prototype.Init = prop.Init;
                      }
                  }
              };
      
              this.P_addPrivate = function () {
                  var name = null,
                      _class = this.P_class,
                      private = this.prop.Private;
      
                  if (private) {
                      //私有屬性/方法直接覆蓋
                      for (name in private) {
                          if (private.hasOwnProperty(name)) {
                              _class.prototype[name] = private[name];
                          }
                      }
                  }
              };
      
              this.P_prepareAndAddPublic = function () {
                  var name = null;
      
                  if (this.prop.Public) {
                      for (name in this.prop.Public) {
                          if (this.prop.Public.hasOwnProperty(name)) {
                              if (this.P_prepareCheck("Public", name) === "continue") {
                                  continue;
                              }
                              this.P_addPublic(name);
                              this.children[name] = this.prop.Public[name];
                          }
                      }
                  }
              };
      
              this.P_addPublic = function (name) {
                  var self = this;
      
                  if (this.parentClass &&
                      typeof this.prop.Public[name] === "function" &&
                      typeof this.P_class.prototype[name] === "function") {
                      this.P_class.prototype[name] = function (name) {
                          return function () {
                              /*
                              //此處不用創建閉包了!因為外面已經創建了閉包,name已經被保存了!
                              self.baseToParrent = function () {
                                  //這個寫法也可以!為什么不用apply修正this也行??!
                                  //this.parentClass.prototype[name](); 
          
                                  //此處的arguments為baseToParrent方法傳入的形參
                                  //注意!要加上“return”,這樣才能返回self.parentClass.prototype[name]的返回值
                                  return self.parentClass.prototype[name].apply(self.parentClass.prototype, arguments);
                              };
                              */
                              //指向子類,可以用于模版模式
                              this.base = self.parentClass.prototype[name];
      
                              //執行fn并返回執行的結果
                              //此處的arguments為F.prototype[name]方法傳入的形參。
                              return self.prop.Public[name].apply(this, arguments);
                          };
      
                      }(name);
                  }
                  else {
                      this.P_class.prototype[name] = this.prop.Public[name];
                  }
              };
      
              this.P_prepareAndAddProtected = function () {
                  var name = null;
      
                  if (this.prop.Protected) {
                      for (name in this.prop.Protected) {
                          if (this.prop.Protected.hasOwnProperty(name)) {
                              if (this.P_prepareCheck("Protected", name) === "continue") {
                                  continue;
                              }
                              this.P_class.prototype[name] = this.prop.Protected[name];
                              this.children[name] = this.prop.Protected[name];
                          }
                      }
                  }
              };
          };
      
      
          //創建抽象類
          //抽象類能夠繼承接口、抽象類以及實體類,但此處約定抽象類只能繼承接口和抽象類,不能繼承實體類!
          //(這樣方便判斷抽象類是否包含全部的父類(接口/抽象類)成員)
      
          function AClass() {
              var that = this;
      
              this.children = {};
              this.P_class = A;
      
              // 本次調用所創建的類(構造函數)
              function A() {
              }
      
              var _getByParent = function (_parent, _prop) {
                  //if (arguments.length === 1) {
                  if (_prop === undefined) {
                      that.prop = _parent;
                      that.parentClass = null;
                      that.interface = null;
                  }
                  else if (typeof _parent === "object") {
      
                      if (!_parent.Class && !_parent.Interface) {
                          throw new Error("Please add AbstractClass or Interface!");
                      }
                      if (_getFunctionName(_parent.Class) === "F" || _getFunctionName(_parent.Interface) === "F") {
                          throw new Error("AbstractClass here can't inherit this.parentClass which is created by Class function!");
                      }
      
                      that.parentClass = _parent.Class;
                      that.interface = _parent.Interface;
                      that.prop = _prop;
                  }
                      //_parent直接為xx,就表示父類為抽象類
                  else if (typeof _parent === "function") {
                      if (_getFunctionName(_parent) === "F") {
                          throw new Error("AbstractClass here can't inherit this.parentClass which is created by Class function!");
                      }
      
                      that.parentClass = _parent;
                      that.interface = null;
                      that.prop = _prop;
                  }
                  else {
                      throw new Error("arguments is not allowed!");
                  }
              };
              this.P_prepareCheck = function (where, name) {
                  //檢查抽象成員,抽象成員放到Public或Protected中
                  if (name === "Abstract") {
                      //this.P_addAbstract(this.prop[where][name], A, this.children);
                      this.P_addAbstract(this.prop[where][name]);
                      return "continue";
                  }
                  //檢查虛方法,虛方法放到Public或Protected中
                  if (name === "Virtual") {
                      this.P_addVirtual(this.prop[where][name]);
                      return "continue";
                  }
              };
              this.buildAClass = function (_parent, _prop) {
                  //取出父類、接口
                  _getByParent(_parent, _prop);
      
                  // 如果此接口需要從其它接口擴展
                  if (this.parentClass) {
                      this.P_inherit();
                  }
      
                  //加入構造函數
                  //抽象類本身因為不能實例化,所以不調用構造函數。
                  //抽象類中的構造函數供子類構造函數中調用。
                  this.P_addInit();
      
                  this.P_addPrivate();
      
                  this.P_prepareAndAddPublic();
      
      
                  //保護成員
                  //_prepareAndAddProtected();
                  this.P_prepareAndAddProtected();
      
                  //放到外面的抽象成員,默認為公有抽象成員
                  this.P_addAbstract(this.prop.Abstract);
      
                  this.P_addStatic();
      
                  //檢查抽象類的公有方法+虛方法+抽象方法是否包含父類的接口方法/屬性
                  this.P_check(null);
      
                  return A;
              };
      
          };
      
      
          AClass.prototype = new Structure();
      
          //創建普通類
          //父類_parent可以為{Class: xx, Interface: xx},或者直接為xx類
          function Class() {
              var that = this;
      
              this.P_class = F;
              this.children = {};
              //當前是否處于創建類的階段。
              this.initializing = false;
              //原型恢復標志,用于防止第一次創建實例時恢復原型
              this.mark_resume = false;
      
              // 本次調用所創建的類(構造函數)
              function F() {
                  //防止第一次創建實例時恢復原型
                  if (that.mark_resume) {
                      //還原原型
                      that.P_extendDeep(F.backUp_prototype, F.prototype);
                  }
                  else {
                      that.mark_resume = true;
                  }
      
                  // 如果當前處于實例化類的階段,則調用Init原型函數
                  if (!that.initializing) {
                      this.Init && this.Init.apply(this, arguments);
                  }
                  /*不能刪除私有成員和保護成員!否則類的成員就不能調用到私有和保護的成員了(因為已經刪除了)!
                  對象的創建算法參考http://www.rzrgm.cn/TomXu/archive/2012/02/06/2330609.html
              
              
              
              
                  //刪除私有成員和保護成員,這樣外界就不能訪問私有和保護成員了!
                  for (name in this) {
                  if (name.search(/(^_)|(^P_)/) !== -1) {
                  delete F.prototype[name];
                  //                                                    this[name] = null;
                  }
                    
                  }
                  */
              }
      
              var _getByParent = function (_parent, _prop) {
                  //if (arguments.length === 1) {
                  if (_prop === undefined) {
                      that.prop = _parent;
                      that.parentClass = null;
                      that.interface = null;
                  }
                      //{Class: xx, Interface: xx}
                  else if (typeof _parent === "object") {
                      if (!_parent.Class && !_parent.Interface) {
                          throw new Error("Please add Class or Interface!");
                      }
      
                      that.parentClass = _parent.Class;
                      that.interface = _parent.Interface;
                      that.prop = _prop;
                  }
                      //直接為xx類
                  else if (typeof _parent === "function") {
                      that.parentClass = _parent;
                      that.interface = null;
                      that.prop = _prop;
                  }
                  else {
                      throw new Error("arguments is not allowed!");
                  }
              };
              //this._addParentSealed = function () {
              //    var name = null;
      
              //    for (name in this.parentClass.prototype) {
              //        if (this.parentClass.prototype.hasOwnProperty(name)) {
              //            //如果不是抽象方法/保護方法/私有方法/接口成員,則加入到this.temp中。
              //            //用于添加父類的密封方法(因為子類并沒有加入父類的密封方法)。
              //            if (!name.match(/^Abstract_/) || !name.match(/^P_/) || !name.match(/^_/) || !name.match(/^Interface_/)) {
              //                this.children[name] = this.parentClass.prototype[name];
              //            }
              //        }
              //    }
              //};
              this.P_prepareCheck = function (where, name) {
                  //檢查虛方法,虛方法放到Public或Protected中
                  if (name === "Virtual") {
                      this.P_addVirtual(this.prop[where][name]);
                      return "continue";
                  }
                  ////密封的方法(不允許子類重寫)
                  //if (name === "Sealed") {
                  //    this.P_addSealed(this.prop[where][name], A);
                  //    return "continue";
                  //}
      
                  return null;
              };
      
              this.buildClass = function (_parent, _prop) {
                  _getByParent(_parent, _prop);
      
                  // 如果此類需要從其它類擴展
                  if (this.parentClass) {
                      this.initializing = true;
                      this.P_inherit();
                      this.initializing = false;
                  }
      
                  this.P_addInit();
      
                  this.P_addPrivate();
      
                  //保護成員
                  this.P_prepareAndAddProtected();
      
                  if (this.prop.Abstract) {
                      throw new Error("Only abstractClass can have abstract methods!");
                  }
                  this.P_prepareAndAddPublic();
      
                  //檢查公有成員和虛函數是否實現了抽象方法/屬性 或 接口方法/屬性
                  this.P_check();
      
                  this.P_addStatic();
      
                  //備份原型
                  F.backUp_prototype = this.P_extendDeep(F.prototype);
      
                  return F;
              };
          };
      
          Class.prototype = new Structure();
      
          /*
          下面的寫法有問題!因為只有載入oopFrame.js時,創建了AClass的實例。
          調用YYC.AClass時,只是引用該實例的buildAClass,而不會再創建AClass實例。
          也就是說,所有YYC.AClass都共用一個AClass的實例!共用AClass實例的屬性(如parent等)!
      
          YYC.AClass = new AClass().buildAClass;
          */
      
      
          YYC.AClass = function (_parent, _prop) {
              return new AClass().buildAClass(_parent, _prop);
          };
          YYC.Class = function (_parent, _prop) {
              return new Class().buildClass(_parent, _prop);
          };
      }());
      View Code

      重構Interface

      去掉i、args變量,提取出buildInterface方法,用oo思想重構Interface:

      function Interface() {
          var that = this;
      
          this.parent = null;
          this.method = null;
          this.attribute = null;
      
          function I() {
          }
      
          function _getByParent(_parent, _method, _attribute) {
              if (typeof _parent === "function") {
                  if (_getFunctionName(_parent) !== "I") {
                      throw new Error("Interface must inherit interface!");
                  }
                  else {
                      that.parent = _parent;
                      //形如“Interface(Parent, "A", "B", "GetName");”
                      if (_method && !_isArray(_method)) {
                          that.method = Array.prototype.slice.call(arguments, 1);
                          that.attribute = null;
                      }
                          //形如“Interface(Parent, ["A", "B", "GetName"], ["a", "c"]);”
                      else {
                          that.method = _method;
                          that.attribute = _attribute;
                      }
                  }
              }
              else {
                  that.parent = null;
                  //形如“Interface("A", "B", "GetName");”
                  if (_method && !_isArray(_method)) {
                      that.method = Array.prototype.slice.call(arguments, 0);
                      that.attribute = null;
                  }
                      //形如“Interface(["A", "B", "GetName"], ["a", "c"]);”
                  else {
                      that.method = arguments[0];
                      that.attribute = arguments[1];
                  }
              }
          };
          function _inherit() {
              I.prototype = new that.parent();
              I.prototype.constructor = I;
          };
          function _addMethod() {
              var i = 0,
                  len = 0;
      
              for (i = 0, len = that.method.length; i < len; i++) {
                  //加上前綴“Interface_”
                  I.prototype["Interface_" + that.method[i]] = function () {
                      throw new Error("This method must be overwrited!");
                  };
              }
          };
          function _addAttribute() {
              var i = 0,
                  len = 0;
      
              if (that.attribute) {
                  if (!_isArray(that.attribute)) {
                      throw new Error("Attribute must be array!");
                  }
                  else {
                      for (i = 0, len = that.method.length; i < len; i++) {
                          //加上前綴“Interface_”
                          I.prototype["Interface_" + that.attribute[i]] = 0;
                      }
                  }
              }
          };
      
          this.buildInterface = function (_parent, _method, _attribute) {
              _getByParent(_parent, _method, _attribute);
              // 如果此接口需要從其它接口擴展
              if (this.parent) {
                  _inherit();
              }
              //方法
              _addMethod();
              //屬性
              _addAttribute();
      
              return I;
          };
      };
      View Code

      增加測試

      增加測試"子類虛方法實現抽象父類的抽象方法時,不拋出異常"、"非抽象類定義抽象成員時拋出異常":

      it("子類虛方法實現抽象父類的抽象方法時,不拋出異常", function () {
          var A = YYC.AClass({
              Abstract: {
                  move: function () { }
              }
          });
          expect(function () {
              YYC.Class(A, {
                  Public: {
                      Virtual: {
                          move: function () { }
                      }
                  }
              });
          }).not.toThrow();
      });
      it("非抽象類定義抽象成員時拋出異常", function () {
          expect(function () {
              YYC.Class({
                  Protected: {
                      Abstract: {
                          move: function () { }
                      }
                  }
              });
          }).toThrow();
          expect(function () {
              YYC.Class({
                  Abstract: {
                      move: function () { }
                  }
              });
          }).toThrow();
      });
      View Code

      重構children

      之前將temp改名為children,但是現在發現這個名字也不恰當,因此根據它的職責“存儲該類成員的名稱,從而用于檢查該類成員是否實現了接口或者父類的抽象成員。”,將其改名為impletationMap。

      將“存儲該類成員的名稱”的操作封裝為函數P_addToImplementMap,放到Structure中:

      this.P_addToImplementMap = function (name, func) {
          this.implementaionMap[name] = func;
      };

      然后又經過了下面的重構

      • 將Structure -> P_prepareAndAddProtected、P_prepareAndAddPublic、P_addVirtual中“將實現方法加入到ImpletationMap中”的職責提取出來形成P_prepareCheck方法,并將原方法改名為P_addPublicMember、P_addProtectedMember。
      • 將Structure ->P_addPrivate、P_addStatic改名為P_addPrivateMember、P_addStaticMember。
      • 將buildClass、buildAClass中的加入外部的抽象成員職責提取為_addOuterAbstract方法。
      • 將Class -> F中恢復F.prototype和初始化職責分別提取為_restorePrototype、_init方法。
      • 將Structure的實例屬性下移到子類中。

      性能優化

      為了優化性能,減少占用的內存,考慮將Interface、Structure、AClass、Class的實例成員改寫成原型成員。

      重構Struture后,Structure的結構為:

      function Structure() {
      };
      Structure.prototype = (function () {}());

       

      當我將AClass改寫成原型形式后,發現測試不能通過,原來是如果寫成原型形式,則AClass的實例就共享同一個內部函數A!這樣會造成不同的類之間互相干擾!

      因此,沒有對Interface、AClass、Class進行該重構。

      改變原有的行為

      我需要增加“支持繼承多個接口”,因此我先添加了測試用例,然后實現。另外我需要增加“限制只能最多繼承一個類”,因此我也先添加測試用例,然后加入限制。

      在改變代碼原有行為時,可能需要改變或增加相應的測試用例。那么不用遲疑,立刻就去做。

      重構注釋

      刪除不必要的注釋,添加重要的算法說明、重構說明等注釋。

      盡量少些注釋,通過對類、函數、屬性等的命名來體現職責和目的。

      以下來自《代碼整潔之道》,可作為參考:
      好注釋:法律信息,提供信息的注釋,對意圖的解釋,闡釋,警示,TODO注釋,放大,共用API中的javadoc
      壞注釋:喃喃自語,多余的注釋,誤導性的注釋,循規式的注釋,日志式注釋,廢話注釋,可怕的廢話,能用函數或變量時就別用注釋,位置標記,括號后面的注釋,歸屬與署名,注釋掉的代碼,函數頭,非共用API中的javadoc。

      完成重構

      最終的測試代碼:

      describe("YOOP", function () {
          it("不存在虛屬性的概念(如果企圖聲明虛屬性,會拋出異常)", function () {
              expect(function () {
                  YYC.Class({
                      Virtual: {
                          a: ""
                      }
                  });
              }).toThrow();
              expect(function () {
                  YYC.AClass({
                      Virtual: {
                          a: ""
                      }
                  });
              }).toThrow();
          });
          it("靜態方法的this是指向類的", function () {
              var A = YYC.Class({
                  Static: {
                      a: 100,
                      method: function () {
                          this.b = 300;
                          return 200;
                      }
                  }
              });
              var result = A.method();
      
              expect(result).toEqual(200);
              expect(A.b).toEqual(300);    //300
          });
      
          describe("測試Class與AClass", function () {
              function testInheritFromOnlyOneClass(_class) {
                  var A = YYC.AClass({});
                  var B = YYC.AClass({});
      
                  expect(function () {
                      YYC[_class](A, B, {});
                  }).toThrow();
                  expect(function () {
                      YYC[_class]({ Class: [A, B] }, {});
                  }).toThrow();
              };
      
              describe("測試類Class", function () {
                  it("可以繼承多個接口。如果不實現會拋出異常", function () {
                      var A = YYC.Interface("m1");
                      var B = YYC.Interface("m2");
      
                      expect(function () {
                          YYC.Class({ Interface: A }, {
                              Public: {
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class({ Interface: [A] }, {
                              Public: {
                              }
                          });
                      }).toThrow();
      
                      expect(function () {
                          YYC.Class({ Interface: [A, B] }, {
                              Public: {
                                  m1: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class({ Interface: [A, B] }, {
                              Public: {
                                  m2: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class({ Interface: [A, B] }, {
                              Public: {
                                  m1: function () { },
                                  m2: function () { }
                              }
                          });
                      }).not.toThrow();
                  });
      
                  it("只能繼承一個類(Class或AClass),否則拋出異常", function () {
                      testInheritFromOnlyOneClass("Class");
                  });
                  it("創建實例時調用構造函數", function () {
                      var A = YYC.Class({
                          Init: function () {
                              this.a = 10;
                          }
                      });
      
                      expect(new A().a).toEqual(10);
                  });
      
                  describe("獲得公有成員", function () {
                      it("如果父類不存在,能夠正確獲得公有方法", function () {
                          var Class = YYC.Class({
                              Public: {
                                  a: function () {
                                      this.b = 1;
                                      return 0;
                                  }
                              }
                          });
      
                          var cla = new Class();
                          var result = cla.a();
      
                          expect(result).toEqual(0);
                          expect(cla.b).toEqual(1);
                      });
                  });
                  it("不能定義抽象成員,否則拋出異常", function () {
                      expect(function () {
                          YYC.Class({
                              Public: {
                                  Abstract: {
                                      move: function () { }
                                  }
                              }
                          })
                      }).toThrow();
                  });
                  it("可以將虛方法定義在外面,表示公有虛方法", function () {
                      var A = YYC.Class({
                          Virtual: {
                              move: function () { }
                          }
                      });
      
                      expect(function () {
                          new A().move()
                      }).not.toThrow();
                  });
                  it("驗證是否實現了接口成員,如果沒有實現會拋出異常", function () {
                      var I = YYC.Interface(["move"], ["a"]);
      
                      expect(function () {
                          YYC.Class({ Interface: I }, {
                              Public: {
                                  a: 0
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class({ Interface: I }, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class({ Interface: I }, {
                              Public: {
                                  a: 0,
                                  move: function () { }
                              }
                          });
                      }).not.toThrow();
                  });
                  it("驗證是否實現了父類抽象成員,如果沒有實現會拋出異常", function () {
                      var A = YYC.AClass({
                          Abstract: {
                              move: function () { },
                              a: 0
                          }
                      });
      
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                                  a: 0
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                                  a: 0,
                                  move: function () { }
                              }
                          });
                      }).not.toThrow();
                  });
              });
      
              describe("測試抽象類AClass", function () {
                  it("可以繼承多個接口(在抽象類中不用實現,可以交給子類Class實現)", function () {
                      var A = YYC.Interface("m1");
                      var B = YYC.Interface(["m2"], ["a"]);
                      var C = YYC.AClass({ Interface: [A, B] }, {});
      
                      expect(function () {
                          YYC.Class(C, {
                              Public: {
                                  m1: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(C, {
                              Public: {
                                  m2: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(C, {
                              Public: {
                                  m1: function () { },
                                  m2: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(C, {
                              Public: {
                                  m1: function () { },
                                  m2: function () { },
                                  a: 1
                              }
                          });
                      }).not.toThrow();
                  });
                  it("只能繼承一個類(Class或AClass),否則拋出異常", function () {
                      testInheritFromOnlyOneClass("AClass");
                  });
                  it("構造函數供子類調用", function () {
                      var A = YYC.AClass({
                          Init: function () {
                              throw new Error();
                          }
                      });
                      var B = YYC.Class(A, {
                          Init: function () {
                              this.a = 10;
                          }
                      });
                      var C = YYC.Class(A, {
                          Init: function () {
                              this.a = 10;
                              this.base();
                          }
                      });
      
                      expect(function () {
                          new B();
                      }).not.toThrow();
                      expect(function () {
                          new C();
                      }).toThrow();
      
                  });
                  it("抽象類如果繼承實體類,會拋出異常", function () {
                      var A = YYC.Class({});
                      expect(function () {
                          YYC.AClass(A, {});
                      }).toThrow();
                  });
                  it("子類虛方法實現抽象父類的抽象方法時,不拋出異常", function () {
                      var A = YYC.AClass({
                          Abstract: {
                              move: function () { }
                          }
                      });
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                                  Virtual: {
                                      move: function () { }
                                  }
                              }
                          });
                      }).not.toThrow();
      
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                              }
                          });
                      }).toThrow();
                  });
                  it("可以將虛方法定義在外面,表示公有虛方法", function () {
                      var A = YYC.AClass({
                          Virtual: {
                              move: function () { }
                          }
                      });
                      var B = YYC.Class(A, {});
      
                      expect(function () {
                          new B().move()
                      }).not.toThrow();
                  });
                  it("可以將抽象成員定義在外面,表示公有抽象成員", function () {
                      var A = YYC.AClass({
                          Abstract: {
                              move: function () { }
                          }
                      });
      
                      expect(function () {
                          YYC.Class(A, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).not.toThrow();
                  });
                  it("不驗證是否實現父類的抽象成員(可以交給子類Class實現)", function () {
                      var A = YYC.AClass({
                          Abstract: {
                              move: function () { },
                              a: 0
                          }
                      });
                      var B = YYC.AClass(A, {});
                      var C = YYC.AClass(B, {});
      
                      expect(function () {
                          YYC.AClass(A, {
                              Public: {
                                  a: 0
                              }
                          });
                      }).not.toThrow();
                      expect(function () {
                          YYC.AClass(A, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).not.toThrow();
      
      
                      expect(function () {
                          YYC.Class(B, {
                              Public: {}
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(B, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).toThrow();
                      expect(function () {
                          YYC.Class(B, {
                              Public: {
                                  move: function () { },
                                  a: 1
                              }
                          });
                      }).not.toThrow();
      
      
                      expect(function () {
                          YYC.Class(C, {
                              Public: {
                                  move: function () { }
                              }
                          });
                      }).toThrow();
                  });
                  it("子類沒有全部實現抽象父類的抽象成員時,拋出異常", function () {
                      var A = YYC.AClass({
                          Init: function (t) {
                              this.a = t;
                              this.b = 2;
                          },
                          Public: {
                              p: function () {
                                  return 0;
                              }
                          },
                          Private: {
                              _m: 1
                          },
                          Protected: {
                              P_h: function () {
                                  return this._m;
                              },
                              P_k: 3
                          },
                          Abstract: {
                              move: function () { },
                              u: 0,
                              t: function () { }
                          }
                      });
      
                      expect(function () {
                          YYC.Class(A, {
                              Init: function () {
                                  this.b = 100;
                                  this.base(200);
                              },
                              Public: {
                                  u: 20
                              }
                          });
                      }).toThrow();
                  });
                  it("子類全部實現抽象父類的抽象成員時,不拋出異常", function () {
                      var A = YYC.AClass({
                          Init: function (t) {
                              this.a = t;
                              this.b = 2;
                          },
                          Public: {
                              p: function () {
                                  return 0;
                              }
                          },
                          Private: {
                              _m: 1
                          },
                          Protected: {
                              P_h: function () {
                                  return this._m;
                              },
                              P_k: 3
                          },
                          Abstract: {
                              move: function () { },
                              u: 0,
                              t: function () { }
                          }
                      });
                      var B = YYC.Class(A, {
                          Init: function () {
                              this.b = 100;
                              this.base(200);
                          },
                          Public: {
                              move: function () {
                                  return this.P_h();
                              },
                              t: function () { },
                              u: 20
                          }
                      });
                      var C = YYC.Class(B, {
                          Public: {
                              move: function () {
                                  var baseResult = this.base();
      
                                  return baseResult;
                              },
                              t: function () { }
                          }
                      });
      
                      var b = new B();
                      var c = new C();
      
                      expect([b.a, b.b]).toEqual([200, 2]);
                      expect([b.p(), b.move(), b.u]).toEqual([0, 1, 20]);
                      expect(c.move()).toEqual(1);
                  });
              });
          });
      
      
          describe("測試接口Interface", function () {
              it("可以繼承多個接口", function () {
                  var A = YYC.Interface("m1");
                  var B = YYC.Interface("m2");
                  var C = YYC.Interface([A, B], "m3");
                  var D = YYC.Interface([A, B], ["m3"]);
                  var E = YYC.Interface([A, B], ["m3"], ["a"]);
                  var F = YYC.Interface(A, "m2");
      
                  expect(C.prototype.Interface_m1).toBeExist();
                  expect(C.prototype.Interface_m2).toBeExist();
                  expect(C.prototype.Interface_m3).toBeExist();
      
                  expect(D.prototype.Interface_m1).toBeExist();
                  expect(D.prototype.Interface_m2).toBeExist();
                  expect(D.prototype.Interface_m3).toBeExist();
      
                  expect(E.prototype.Interface_m1).toBeExist();
                  expect(E.prototype.Interface_m2).toBeExist();
                  expect(E.prototype.Interface_m3).toBeExist();
                  expect(E.prototype.Interface_a).toEqual(0);
      
                  expect(F.prototype.Interface_m1).toBeExist();
                  expect(F.prototype.Interface_m2).toBeExist();
              });
          });
      
          describe("集成測試", function () {
              it("測試解決“若父類的屬性為引用類型(數組或對象)a,則如果子類的實例s1對a進行修改或者sub調用修改a的方法,則第二次創建實例s2的a為修改過后的a!”的問題", function () {
                  var Parent = YYC.AClass({
                      Init: function () {
                          console.log("Parent Init!");
                      },
                      Public: {
                          a: [],
                      }
                  });
                  var Sub = YYC.Class(Parent, {
                      Init: function () {
                      },
                      Public: {
                      }
                  });
      
                  var t = new Sub();
                  t.a.push("a");
                  var m = new Sub();
      
                  expect(m.a).toEqual([]);
              });
              it("測試解決“若父類Parent的屬性為引用類型(數組或對象)a,有兩個子類Sub1、Sub2。如果子類Sub1的實例s1對a進行修改或者sub調用修改a的方法,則子類Sub2的實例的a為修改過后的a!”的問題", function () {
                  var Parent = YYC.AClass({
                      Init: function () {
                          console.log("Parent Init!");
                      },
                      Public: {
                          a: [],
                          add: function () {
                              this.a.push("a");
                          }
                      }
                  });
                  var Sub1 = YYC.Class(Parent, {
                      Init: function () {
                      },
                      Public: {
                      }
                  });
                  var Sub2 = YYC.Class(Parent, {
                      Init: function () {
                      }
                  });
      
                  var t = new Sub1();
                  t.a.push("a");
                  var k = new Sub2();
      
                  expect(k.a).toEqual([]);
      
              });
              it("測試解決“若A1為抽象類,A2(抽象類)繼承于A1,B(類)繼承于A2,A1、A2、B都有同名方法a,A2和B在a方法中都通過this.baseClass調用父類同名方法。則如果B的實例b調用a方法,則A2、B的a方法中的this.baseClass均指向A2(照理說A2的this.baseClass應該指向A1)!”的問題", function () {
                  var A1 = YYC.AClass({
                      Public: {
                          arr: [],
                          a: function () {
                              this.arr.push(1);
                          }
                      }
                  });
                  var A2 = YYC.AClass(A1, {
                      Public: {
                          a: function () {
                              this.arr.push(2);
                              this.baseClass.a.call(this, null);
                          }
                      }
                  });
                  var B = YYC.Class(A2, {
                      Public: {
                          a: function () {
                              this.arr.push(3);
                              this._baseClass.a.call(this, null);
      
                              return this.arr;
                          }
                      }
                  });
                  var b = new B();
      
                  expect(b.a()).toEqual([3, 2, 1]);
              });
          });
      });
      View Code

      最終的YOOP代碼:

      (function () {
      
          window.YYC = window.YYC || {};
      
          /************************************************** String對象擴展 ************************************************************/
          if (!String.prototype.contain) {
              String.prototype.contain = function (str) {
                  var reg = new RegExp(str);  //str需要轉義
                  if (this.match(reg)) {
                      return true;
                  }
                  else {
                      return false;
                  }
              }
          }
      
          /*****************************************************************************************************************************/
              //獲得在原型prototype中不存在同名的str。
              //如果有同名,則加上前綴"_"
          function getNoRepeatStrInPrototype(prototype, str) {
              var new_str = "";
      
              if (!prototype[str]) {
                  return str;
              }
              new_str = "_" + str;
      
              return arguments.callee(prototype, new_str);
          }
      
      
          function extendDeep(parent, child) {
              var i = null,
                  len = 0,
                  toStr = Object.prototype.toString,
                  sArr = "[object Array]",
                  sOb = "[object Object]",
                  type = "",
                  _child = null;
      
              //數組的話,不獲得Array原型上的成員。
              if (toStr.call(parent) === sArr) {
                  _child = child || [];
      
                  for (i = 0, len = parent.length; i < len; i++) {
                      type = toStr.call(parent[i]);
                      if (type === sArr || type === sOb) {    //如果為數組或object對象
                          _child[i] = type === sArr ? [] : {};
                          arguments.callee(parent[i], _child[i]);
                      } else {
                          _child[i] = parent[i];
                      }
                  }
              }
              //對象的話,要獲得原型鏈上的成員。因為考慮以下情景:
              //類A繼承于類B,現在想要拷貝類A的實例a的成員(包括從類B繼承來的成員),那么就需要獲得原型鏈上的成員。
              else if (toStr.call(parent) === sOb) {
                  _child = child || {};
      
                  for (i in parent) {
                      type = toStr.call(parent[i]);
                      if (type === sArr || type === sOb) {
                          _child[i] = type === sArr ? [] : {};
                          arguments.callee(parent[i], _child[i]);
                      } else {
                          _child[i] = parent[i];
                      }
                  }
              }
              else {
                  _child = parent;
              }
      
              return _child;
          };
          function getFunctionName(fn) {
              var name = "";
      
              if (!fn) {
                  return null;
              }
      
              name = fn.toString().match(/^.*function\s*([^\(]*)/);
              return name === null ? name : name[1];
          };
      
          function isArray(val) {
              return Object.prototype.toString.call(val) === "[object Array]";
          };
      
          /*
           Structure寫成原型形式,而Interface、AClass、Class不寫成原型形式!(如寫成:
           Interface.prototype = (function(){
           function I(){
           };
      
           return {
           ...
           };
           }());
           )
           因為如果寫成原型形式,則Interface/AClass/Class的實例就共享同一個I/A/F類!這樣會造成不同的類之間互相干擾!
           */
      
      
          (function () {
              function Interface() {
                  var that = this;
      
                  this.parent = null;
                  this.method = null;
                  this.attribute = null;
      
                  function I() {
                  }
      
                  function _getByParent(_parent, _method, _attribute) {
                      if (_hasParent(_parent)) {
                          _checkInheritInterface(_parent);
                          that.parent = isArray(_parent) ? _parent : [_parent];
      
                          //形如“Interface(Parent, "A", "B", "GetName");”
                          if (_method && !isArray(_method)) {
                              that.method = Array.prototype.slice.call(arguments, 1);
                              that.attribute = null;
                          }
                          //形如“Interface(Parent, ["A", "B", "GetName"], ["a", "c"]);”
                          else {
                              that.method = _method;
                              that.attribute = _attribute;
                          }
                      }
                      else {
                          that.parent = null;
                          //形如“Interface("A", "B", "GetName");”
                          if (_parent && !isArray(_parent)) {
                              that.method = Array.prototype.slice.call(arguments, 0);
                              that.attribute = null;
                          }
                          //形如“Interface(["A", "B", "GetName"], ["a", "c"]);”
                          else {
                              that.method = arguments[0];
                              that.attribute = arguments[1];
                          }
                      }
      
                      _checkMethod();
                  };
                  function _hasParent(_parent) {
                      return typeof _parent === "function" || (isArray(_parent) && typeof _parent[0] === "function");
                  };
                  function _checkInheritInterface(_parent) {
                      var i = 0,
                          len = 0;
      
                      for (i = 0, len = _parent.length; i < len; i++) {
                          if (getFunctionName(_parent[i]) !== "I") {
                              throw new Error("Interface must inherit interface!");
                          }
                      }
                  };
                  function _checkMethod() {
                      if (!that.method) {
                          throw new Error("Interface must has methods");
                      }
                  };
                  function _inherit() {
                      var i = 0,
                          len = 0;
      
                      for (i = 0, len = that.parent.length; i < len; i++) {
                          extendDeep(that.parent[i].prototype, I.prototype);
                      }
                      I.prototype.constructor = I;
                  };
                  function _addMethod() {
                      var i = 0,
                          len = 0;
      
                      for (i = 0, len = that.method.length; i < len; i++) {
                          if (that.method[i] === undefined) {
                              continue;
                          }
                          //加上前綴“Interface_”
                          I.prototype["Interface_" + that.method[i]] = function () {
                              throw new Error("This method must be overwrited!");
                          };
                      }
                  };
                  function _addAttribute() {
                      var i = 0,
                          len = 0;
      
                      if (that.attribute) {
                          if (!isArray(that.attribute)) {
                              throw new Error("Attribute must be array!");
                          }
                          else {
                              for (i = 0, len = that.method.length; i < len; i++) {
                                  //加上前綴“Interface_”
                                  I.prototype["Interface_" + that.attribute[i]] = 0;
                              }
                          }
                      }
                  };
      
                  this.buildInterface = function (_parent, _method, _attribute) {
                      _getByParent(_parent, _method, _attribute);
                      if (this.parent) {
                          _inherit();
                      }
                      _addMethod();
                      _addAttribute();
      
                      return I;
                  };
              };
      
              YYC.Interface = function (_parent, _method, _attribute) {
                  return new Interface().buildInterface(_parent, _method, _attribute);
              };
          }());
      
          (function () {
      
              function Structure() {
              };
              Structure.prototype = (function () {
                  return {
                      _addToImplementMap: function (name, func) {
                          this.implementaionMap[name] = func;
                      },
                      _prepareCheckFor: function (module) {
                          var name = null;
      
                          if (module) {
                              for (name in module) {
                                  if (module.hasOwnProperty(name)) {
                                      this._prepareCheckForSpecial(name, module);
                                      this._addToImplementMap(name, module[name]);
                                  }
                              }
                          }
                      },
                      _prepareCheckForSpecial: function (name, module) {
                          this._addVirtualToImplementMap(name, module);
                      },
                      _addVirtualToImplementMap: function (name, module) {
                          var name2 = "";
      
                          if (name === "Virtual") {
                              for (name2 in module[name]) {
                                  if (module[name].hasOwnProperty(name2)) {
                                      this._addToImplementMap(name2, module[name][name2]);
                                  }
                              }
                          }
                      },
                      P_checkImplementationOfAbstract: function () {
                          var name = "",
                              parentClass = this.parentClass;
      
                          if (this.parentClass) {
                              for (name in parentClass.prototype) {
                                  if (parentClass.prototype.hasOwnProperty(name)) {
                                      if (name === "constructor") {
                                          continue;
                                      }
                                      if (name.contain("Abstract_")) {
                                          if (typeof parentClass.prototype[name] === "function") {
                                              this._checkAbstractMethod(name);
                                          }
                                          else {
                                              this._checkAbstractAttribute(name);
                                          }
                                      }
                                  }
                              }
                          }
                      },
                      _checkAbstractMethod: function (name) {
                          var parentClass = this.parentClass,
                              implementaionMap = this.implementaionMap;
      
                          if (this._noMethodForAbstract(implementaionMap, name) && this._noMethodForAbstract(parentClass.prototype, name)) {
                              throw new Error("Abstract method '" + name + "' must be overwrited!");
                          }
                      },
                      _checkAbstractAttribute: function (name) {
                          var parentClass = this.parentClass,
                              implementaionMap = this.implementaionMap;
      
                          if (this._noAttritubeForAbstract(implementaionMap, name) && this._noAttritubeForAbstract(parentClass.prototype, name)) {
                              throw new Error("Abstract attribute '" + name + "' must be overwrited!");
                          }
                      },
                      P_checkImplementationOfInterface: function (_interface) {
                          var name = "";
      
                          for (name in _interface.prototype) {
                              if (!name.contain("Interface_")) {
                                  continue;
                              }
                              if (typeof _interface.prototype[name] === "function") {
                                  this._checkInterfaceMethod(name);
                              }
                              else {
                                  this._checkInterfaceAttribute(name);
                              }
                          }
                      },
                      _checkInterfaceMethod: function (name) {
                          var implementaionMap = this.implementaionMap,
                              parentClassPrototype = this.parentClass ? this.parentClass.prototype : {};
      
                          if (this._noMethodForInterface(implementaionMap, name) && this._noMethodForInterface(parentClassPrototype, name)) {
                              throw new Error("Interface method '" + name + "' must be overwrited!");
                          }
                      },
                      _checkInterfaceAttribute: function (name) {
                          var implementaionMap = this.implementaionMap,
                              parentClassPrototype = this.parentClass ? this.parentClass.prototype : {};
      
                          if (this._noAttritubeForInterface(implementaionMap, name) && this._noAttritubeForInterface(parentClassPrototype, name)) {
                              throw new Error("Interface attribute '" + name + "' must be overwrited!");
                          }
                      },
                      _noMethodForAbstract: function (_class, name) {
                          return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] !== "function";
                      },
                      _noAttritubeForAbstract: function (_class, name) {
                          return _class[name.slice(9)] === undefined || typeof _class[name.slice(9)] === "function";
                      },
                      _noMethodForInterface: function (_class, name) {
                          return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] !== "function";
                      },
                      _noAttritubeForInterface: function (_class, name) {
                          return _class[name.slice(10)] === undefined || typeof _class[name.slice(10)] === "function";
                      },
                      P_addAbstract: function (abstract) {
                          var name = "",
                              _class = this.P_class;
      
                          for (name in abstract) {
                              if (abstract.hasOwnProperty(name)) {
                                  //抽象方法前面加"Abstract_"前綴
                                  _class.prototype["Abstract_" + name] = abstract[name];
                              }
                          }
                      },
                      //加入虛方法(不能為虛屬性)
                      P_addVirtualAndCheck: function (virtual) {
                          var name = "",
                              _class = this.P_class;
      
                          for (name in virtual) {
                              if (virtual.hasOwnProperty(name)) {
                                  if (typeof virtual[name] !== "function") {
                                      throw new Error("Virtual attribute is not allowed!");
                                  }
                                  else {
                                      _class.prototype[name] = virtual[name];
                                  }
                              }
                          }
                      },
                      P_addStaticMember: function () {
                          var Static = null,
                              k = null,
                              _class = this.P_class,
                              prop = this.prop;
      
                          Static = prop.Static ? prop.Static : null;
      
                          for (k in Static) {
                              _class[k] = Static[k];
                          }
                      },
                      P_inherit: function () {
                          var _class = this.P_class,
                              parentClass = this.parentClass;
      
                          _class.prototype = extendDeep(parentClass.prototype);
                          _class.prototype.constructor = _class;
      
                          // 如果父類存在,則實例對象的baseClass指向父類的原型。
                          // 這就提供了在實例對象中調用父類方法的途徑。
                          //baseClass的方法是指向this.parentClass.prototype的,不是指向(子類)的!
                          _class.prototype[getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;
                      },
                      P_addInit: function () {
                          var _class = this.P_class,
                              parentClass = this.parentClass,
                              prop = this.prop;
      
                          if (prop.Init) {
                              if (parentClass &&
                                  typeof prop.Init === "function" &&
                                  typeof _class.prototype.Init === "function") {
                                  _class.prototype.Init = function (name) {
                                      return function () {
                                          this.base = parentClass.prototype[name];
      
                                          return prop[name].apply(this, arguments);
                                      };
                                  }("Init");
                              }
                              else {
                                  _class.prototype.Init = prop.Init;
                              }
                          }
                      },
                      P_addPrivateMember: function () {
                          var name = null,
                              _class = this.P_class,
                              private = this.prop.Private;
      
                          if (private) {
                              for (name in private) {
                                  if (private.hasOwnProperty(name)) {
                                      _class.prototype[name] = private[name];
                                  }
                              }
                          }
                      },
                      P_addPublicMember: function () {
                          var name = null;
      
                          if (this.prop.Public) {
                              for (name in this.prop.Public) {
                                  if (this.prop.Public.hasOwnProperty(name)) {
                                      if (this.P_addSpecial("Public", name) === "continue") {
                                          continue;
                                      }
                                      this._addPublic(name);
                                  }
                              }
                          }
                      },
                      _addPublic: function (name) {
                          var parentClass = this.parentClass,
                              prop = this.prop,
                              P_class = this.P_class;
      
                          if (parentClass &&
                              typeof prop.Public[name] === "function" &&
                              typeof P_class.prototype[name] === "function") {
                              P_class.prototype[name] = function (name) {
                                  return function () {
                                      this.base = parentClass.prototype[name];
      
                                      return prop.Public[name].apply(this, arguments);
                                  };
                              }(name);
                          }
                          else {
                              P_class.prototype[name] = prop.Public[name];
                          }
                      },
                      P_prepareCheck: function () {
                          this._prepareCheckFor(this.prop.Public);
                          this._prepareCheckFor(this.prop.Protected);
                      },
                      P_addProtectedMember: function () {
                          var name = null;
      
                          if (this.prop.Protected) {
                              for (name in this.prop.Protected) {
                                  if (this.prop.Protected.hasOwnProperty(name)) {
                                      if (this.P_addSpecial("Protected", name) === "continue") {
                                          continue;
                                      }
                                      this.P_class.prototype[name] = this.prop.Protected[name];
                                  }
                              }
                          }
                      }
                  }
              }());
      
              //創建抽象類
              //抽象類能夠繼承接口、抽象類以及實體類,但此處約定抽象類只能繼承接口和抽象類,不能繼承實體類!
              //(這樣方便判斷抽象類是否包含全部的父類(接口/抽象類)成員)
      
              function AClass() {
                  var that = this;
      
                  this.P_class = A;
                  this.implementaionMap = {};
                  this.parentClass = null;
                  this.interface = null;
                  this.prop = null;
      
                  // 創建的類(構造函數)
                  function A() {
                  };
      
                  function __getByParent(args) {
                      var _parent = args[0],
                          _prop = args[1];
      
                      __checkOnlyOneParentClass(args);
      
                      if (_prop === undefined) {
                          that.prop = _parent;
                          that.parentClass = null;
                          that.interface = null;
                      }
                      //{Class: xx, Interface: xx}
                      else if (typeof _parent === "object") {
                          if (!_parent.Class && !_parent.Interface) {
                              throw new Error("Please add AbstractClass or Interface!");
                          }
                          that.parentClass = _parent.Class;
                          if (isArray(_parent.Interface)) {
                              that.interface = _parent.Interface;
                          }
                          else if (typeof _parent.Interface === "function") {
                              that.interface = [_parent.Interface];
                          }
                          that.prop = _prop;
                      }
                      //直接為xx抽象類
                      else if (typeof _parent === "function") {
                          that.parentClass = _parent;
                          that.interface = null;
                          that.prop = _prop;
                      }
                      else {
                          throw new Error("arguments is not allowed!");
                      }
                      if (__isInheritFromClass()) {
                          throw new Error("AbstractClass can't inherit class!");
                      }
                  };
                  function __checkOnlyOneParentClass(args) {
                      if (args.length >= 3) {
                          throw new Error("AbstractClass can only inherit from one parentClass");
                      }
      
                      if (args[0].Class) {
                          if (isArray(args[0].Class) && args[0].Class.length >= 2) {
                              throw new Error("AbstractClass can only inherit from one parentClass");
                          }
                      }
                  };
                  function __isInheritFromClass() {
                      return getFunctionName(that.parentClass) === "F";
                  };
                  this.P_inherit = function () {
                      var parentClass = this.parentClass;
      
                      if (this.parentClass) {
                          A.prototype = extendDeep(parentClass.prototype);
                          A.prototype.constructor = A;
      
                          // 如果父類存在,則實例對象的baseClass指向父類的原型。
                          // 這就提供了在實例對象中調用父類方法的途徑。
                          //baseClass的方法是指向this.parentClass.prototype的,不是指向(子類)的!
                          A.prototype[getNoRepeatStrInPrototype(parentClass.prototype, "baseClass")] = parentClass.prototype;
                      }
      
                      if (this.interface) {
                          var i = 0,
                              len = 0;
      
                          for (i = 0, len = this.interface.length; i < len; i++) {
                              extendDeep(this.interface[i].prototype, A.prototype);
                          }
                      }
                  };
                  this.P_addSpecial = function (moduleName, name) {
                      if (name === "Abstract") {
                          this.P_addAbstract(this.prop[moduleName][name]);
                          return "continue";
                      }
                      if (name === "Virtual") {
                          this.P_addVirtualAndCheck(this.prop[moduleName][name]);
                          return "continue";
                      }
                      return null;
                  };
      
                  this.buildAClass = function (args) {
                      __getByParent(args);
      
                      this.P_inherit();
      
                      //抽象類本身因為不能實例化,所以不在A中調用構造函數Init。
                      //抽象類中的構造函數供子類構造函數中調用。
                      this.P_addInit();
                      this.P_addPrivateMember();
                      this.P_addProtectedMember();
                      this.P_addPublicMember();
                      this.P_addStaticMember();
                      __addOuterAbstract();
                      __addOuterVirtual();
      
                      this.P_prepareCheck();
      
                      return A;
                  };
      
                  //放到外面的抽象成員,默認為公有抽象成員
                  function __addOuterAbstract() {
                      if (that.prop.Abstract) {
                          that.P_addAbstract(that.prop.Abstract);
                      }
                  };
                  function __addOuterVirtual() {
                      if (that.prop.Virtual) {
                          that.P_addVirtualAndCheck(that.prop.Virtual);
                      }
                  };
              };
      
              AClass.prototype = new Structure();
      
              //創建普通類
              //父類_parent可以為{Class: xx, Interface: xx},或者直接為xx類
              function Class() {
                  var that = this;
      
                  this.implementaionMap = {};
                  this.parentClass = null;
                  this.interface = null;
                  this.prop = null;
      
                  this.P_class = F;
                  //當前是否處于創建類的階段。
                  this.initializing = false;
      
      
                  // 創建的類(構造函數)
                  function F() {
                      var self = this,
                          args = arguments;
      
                      function _restorePrototype() {
                          extendDeep(F.prototype, self);
                      };
                      function _init() {
                          // 如果當前處于實例化類的階段,則調用構造函數Init
                          if (!that.initializing) {
                              self.Init && self.Init.apply(self, args);
                          }
                      };
      
                      _restorePrototype();
                      _init();
      
                      /*不能刪除私有成員和保護成員!否則類的成員就不能調用到私有和保護的成員了(因為已經刪除了)!
                       對象的創建算法參考http://www.rzrgm.cn/TomXu/archive/2012/02/06/2330609.html
      
      
      
      
                       //刪除私有成員和保護成員,這樣外界就不能訪問私有和保護成員了!
                       for (name in this) {
                       if (name.search(/(^_)|(^P_)/) !== -1) {
                       delete F.prototype[name];
                       //                                                    this[name] = null;
                       }
      
                       }
                       */
                  }
      
                  function __getByParent(args) {
                      var _parent = args[0],
                          _prop = args[1];
      
                      __checkOnlyOneParentClass(args);
      
                      if (_prop === undefined) {
                          that.prop = _parent;
                          that.parentClass = null;
                          that.interface = null;
                      }
                      //{Class: xx, Interface: xx}
                      else if (typeof _parent === "object") {
                          if (!_parent.Class && !_parent.Interface) {
                              throw new Error("Please add Class or Interface!");
                          }
                          that.parentClass = _parent.Class;
                          if (isArray(_parent.Interface)) {
                              that.interface = _parent.Interface;
                          }
                          else if (typeof _parent.Interface === "function") {
                              that.interface = [_parent.Interface];
                          }
                          that.prop = _prop;
                      }
                      //直接為xx類
                      else if (typeof _parent === "function") {
                          that.parentClass = _parent;
                          that.interface = null;
                          that.prop = _prop;
                      }
                      else {
                          throw new Error("arguments is not allowed!");
                      }
                  };
                  function __checkOnlyOneParentClass(args) {
                      if (args.length >= 3) {
                          throw new Error("class can only inherit from one parentClass");
                      }
      
                      if (args[0].Class) {
                          if (isArray(args[0].Class) && args[0].Class.length >= 2) {
                              throw new Error("class can only inherit from one parentClass");
                          }
                      }
                  };
                  this.P_addSpecial = function (moduleName, name) {
                      if (name === "Abstract") {
                          throw new Error("class can't have abstract members");
                      }
                      if (name === "Virtual") {
                          this.P_addVirtualAndCheck(this.prop[moduleName][name]);
                          return "continue";
                      }
                      return null;
                  };
                  this.buildClass = function (args) {
                      __getByParent(args);
      
                      if (this.parentClass) {
                          this.initializing = true;
                          this.P_inherit();
                          this.initializing = false;
                      }
      
                      this.P_addInit();
                      this.P_addPrivateMember();
                      this.P_addProtectedMember();
                      this.P_addPublicMember();
                      this.P_addStaticMember();
                      __addOuterAbstract();
                      __addOuterVirtual();
      
                      this.P_prepareCheck();
                      this.P_checkImplementationOfAbstract();
                      __checkEachImplementationOfInterface();
      
                      return F;
                  };
                  function __checkEachImplementationOfInterface() {
                      if (that.interface) {
                          var i = 0,
                              len = 0;
      
                          for (i = 0, len = that.interface.length; i < len; i++) {
                              that.P_checkImplementationOfInterface(that.interface[i]);
                          }
                      }
                      if (__hasInterfaceInheritFromParentClass()) {
                          that.P_checkImplementationOfInterface(that.parentClass);
                      }
                  };
                  function __hasInterfaceInheritFromParentClass() {
                      var name = "";
      
                      for (name in F.prototype) {
                          if (F.prototype.hasOwnProperty(name)) {
                              if (name.contain("Interface_")) {
                                  return true;
                              }
                          }
                      }
      
                      return false;
                  };
                  function __addOuterAbstract() {
                      if (that.prop.Abstract) {
                          throw new Error("class can't have abstract members!");
                      }
                  };
                  function __addOuterVirtual() {
                      if (that.prop.Virtual) {
                          that.P_addVirtualAndCheck(that.prop.Virtual);
                      }
                  };
              };
      
              Class.prototype = new Structure();
      
              /*
               下面的寫法有問題!因為只有載入YOOP.js時,創建了AClass的實例。
               調用YYC.AClass時,只是引用該實例的buildAClass,而不會再創建AClass實例。
               也就是說,所有YYC.AClass都共用一個AClass的實例!共用AClass實例的屬性(如parent等)!
      
               YYC.AClass = new AClass().buildAClass;
               */
      
      
              YYC.AClass = function () {
                  return new AClass().buildAClass(arguments);
              };
              YYC.Class = function () {
                  return new Class().buildClass(arguments);
              };
          }());
      }());
      View Code

      總結

      我花了5天的時間來對YOOP進行重構,這樣效率其實是比較低下的。我們應該采用TDD開發,在需要重構的時候立馬重構。

      因為隨著人們對問題研究的深入,人們對問題的了解也越來越多,所以需要及時的反饋修正,對之前做的設計或代碼進行修改,然后運行測試,保證測試的通過,然后再進行下一步的研究。這是一個迭代的過程,每次重構,都能反映自己的最新的理解。

      為了保證代碼質量,為了便于二次開發擴展,為了增強可讀性,為了反映自己最新的理解,為了追求代碼之美、設計之美,都需要我們在堅實的測試套件下,不斷地重構改進。

      需要注意的是,不僅是產品代碼需要重構,測試代碼也一樣需要重構。

      對于我們個人的修煉而言,應該時刻地重構;對于工程方面而言,有時為了趕進度,會對質量方面要求降低。但是作為程序員,應該對自己編寫的代碼負責,在趕進度的情況下,我們應該在項目結束或相對輕松的時間里,對代碼進行重構,而且可以進行抽象、封裝,提煉出自己的產品和文檔。

      只有通過不斷地改進、總結,我們才能不斷地進步。

      posted @ 2013-06-08 17:54  楊元超  閱讀(921)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 欧美日韩v| 国产360激情盗摄全集| 2020国产欧洲精品网站| 小嫩批日出水无码视频免费| 成年视频人免费网站动漫在线 | 日韩精品久久久肉伦网站| 国产午夜亚洲精品一区| 人妻影音先锋啪啪av资源| 国产成人a在线观看视频| 国产成人高清亚洲综合| 久久久久国色av免费看| 亚洲综合国产激情另类一区| 老太脱裤子让老头玩xxxxx| 亚洲中文字幕精品无人区| 精品无码久久久久久尤物| 国产精品丝袜亚洲熟女| 日韩精品三区二区三区| 五月天中文字幕mv在线| 久久大香萑太香蕉av黄软件| 延寿县| 丰满少妇特黄一区二区三区| 亚洲av无码之国产精品网址蜜芽| 青青草无码免费一二三区| 一区二区三区久久精品国产| 国产国语一级毛片| 亚洲精品乱码免费精品乱| 91中文字幕在线一区 | 国产片AV国语在线观看手机版| 中字幕人妻一区二区三区| 国产91精品调教在线播放| 丰满人妻一区二区三区无码AV| 亚洲最大av资源站无码av网址| 午夜福利国产片在线视频| 北岛玲中文字幕人妻系列| 亚洲AV无码一区二区一二区色戒| 97精品久久久大香线焦| 一级国产在线观看高清| 在线精品另类自拍视频| 男人狂桶女人出白浆免费视频| 国产日产欧产美韩系列麻豆| 亚洲中文字幕日产无码成人片 |