1. "use strict";
  2. /**
  3. 面向对象思想的辅助实现模块;
  4. Feartures :
  5. 1. klass :类继承;实现执行指针,类常用方法,继承路径
  6. 2. factory :对象/类工厂方法;
  7.  
  8. Update Note:
  9. + 2014.6 :Created
  10.  
  11. @module OOP
  12. */
  13. _stDefine('oop', function(st) {
  14. //初始化扩展函数
  15. var _onKlassInit = st.promiseEvent(),
  16. /**
  17. * klass的基类对象
  18. * @class klassBase
  19. */
  20. _klassBase = {
  21. /**
  22. 调用原型链方法
  23. @method callProto
  24. @param name {string} 需要执行的原型链方法名
  25. @param [args] {array} 执行参数
  26. @return [object] 返回执行结果
  27. @demo test/base/oop.js [klassBase - callProto] {执行原型链方法}
  28. */
  29. callProto : function(name,args){
  30. var fn = this._$fn[name];
  31. if(fn)
  32. return fn.apply(this,args);
  33. },
  34. /**
  35. 获取基类对象
  36. @method getBase
  37. @param [baseName] {string} 基类名称,不设置则返回父类
  38. @return [object] 返回基类
  39. @demo test/base/oop.js [klassBase - getBase] {获取基类对象}
  40. */
  41. getBase: function(baseName) {
  42. var self = this,
  43. parent = self._$super;
  44.  
  45. if (baseName && typeof baseName == 'number')
  46. baseName = self._$inheirts[baseName];
  47.  
  48. if (parent) {
  49. if (baseName) {
  50. while (parent && parent._$kName != baseName) {
  51. parent = parent._$super;
  52. }
  53. } else if (parent._$kName == self._$kName) {
  54. return null;
  55. }
  56. }
  57. return parent;
  58. },
  59. /**
  60. 调用基类的方法
  61. @method callBase
  62. @param {string} fnName 方法名称
  63. @param {string} [baseName] 基类名称
  64. @param {array} [args] 方法参数数组
  65. @return {object} 执行结果
  66. @demo test/base/oop.js [klassBase - callBase] {调用父类}
  67. @demo test/base/oop.js [muilt heirht - callBase] {多级继承示例}
  68. */
  69. callBase: function(fnName, baseName, args) {
  70. var self = this,
  71. base = self._$super,
  72. fn, result, current, indicator = self._$indicator;
  73.  
  74. if (!base)
  75. return;
  76.  
  77. if (arguments.length < 3) {
  78. args = baseName;
  79. baseName = null;
  80. }
  81.  
  82. if (baseName)
  83. base = self.getBase(baseName);
  84. else if (current = indicator[fnName])
  85. base = current._$super || current.fn._$super || current;
  86.  
  87. if (base && (fn = base[fnName])) {
  88. indicator[fnName] = base;
  89. result = fn.apply(this, args);
  90. indicator[fnName] = null;
  91. }
  92. return result;
  93. },
  94. /**
  95. 类扩展方法
  96. @method extend
  97. @param {object} prop 扩展的属性和方法对象
  98. @chainable
  99. @demo test/base/oop.js [klassBase - extend] {类扩展}
  100. */
  101. extend: function(prop) {
  102. st.mergeObj(this, prop);
  103. return this;
  104. }
  105. };
  106.  
  107. st.conf('oop-KlassBase',_klassBase);
  108.  
  109. /**
  110. js类创建,具有执行指针功能(解决了多级继承域对象的问题)
  111.  
  112. 此外提供两种全局扩展方式:
  113. 1. 基于原形链的基类扩展,使用st.conf('oop-KlassBase'),可以取到基类对象进行扩展
  114. 2. 在类初始化时,对实例化的对象进行扩展,可以使用st.onKlassInit对象进行添加扩展方法。st.onKlassInit 是promiseEvent对象,st.onKlassInit(obj,config);
  115.  
  116. @class klass
  117. @constructor
  118. @extend klassBase
  119. @param {string} name 类名称
  120. @param {object} prop 类的属性和方法
  121. @param {klass|object|function} [parent] 父类
  122. @param {object} [config] 扩展参数
  123. @return {klass} 返回类
  124. @demo test/base/oop.js [class init] {实例化}
  125. @demo test/base/oop.js [inheirt] {类继承}
  126. @demo test/base/oop.js [klass prop check] {继承特性检查}
  127. @demo test/base/oop.js [muilt heirht - callBase] {多级继承}
  128. */
  129. function klass(name, prop, parent, config) {
  130. var _super, _proto, _prop = prop,
  131. _inheirts = [name],
  132. _obj = function() {
  133. var self = this,
  134. args = arguments,
  135. len = args.length;
  136.  
  137. //自执行初始化判断
  138. if (!(self instanceof _obj)) {
  139. if (len === 0)
  140. return new _obj();
  141. if (len < 4)
  142. return new _obj(args[0], args[1], args[2]);
  143. else if (len < 7)
  144. return new _obj(args[0], args[1], args[2], args[3], args[4], args[5]);
  145. else
  146. return new _obj(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
  147. }
  148. //设置指针对象
  149. self._$indicator = {};
  150. //设置原型链
  151. self._$fn = _proto;
  152. //执行扩展方法
  153. _onKlassInit.fireWith(self,config);
  154. //klassInit默认初始化
  155. self.klassInit && self.klassInit.apply(self, args);
  156. }
  157.  
  158. if (parent) {
  159. _super = parent.prototype || parent;
  160. _proto = _obj.prototype = Object.create(_super);
  161. _proto._$super = _super;
  162. _proto.constructor = parent;
  163. //添加父的继承路径
  164. if (_super._$inheirts)
  165. _inheirts = _inheirts.concat(_super._$inheirts);
  166. else
  167. _inheirts.push(parent.name);
  168. } else
  169. _proto = st.mergeObj(_obj.prototype, _klassBase);
  170.  
  171. _obj.fn = _proto;
  172.  
  173. st.mergeMulti([_proto, _prop,{
  174. //类标示
  175. _$klass: true,
  176. //类名
  177. _$kName: name,
  178. //继承链
  179. _$inheirts: _inheirts
  180. }]);
  181.  
  182. return _obj;
  183. }
  184.  
  185. // _onKlassInit.add('attachTrigger', function(config) {
  186. // var trigger = config.trigger;
  187. // trigger && st.attachTrigger(this, trigger.iFace, trigger.mode);
  188. // })
  189. /**
  190. * factory并不只是指的是工厂模式。在factory要求定义一个基础对象,这个对象可以是基类,也可以是模板对象或者是接口。然后factory就已此基础对象为基础,其他添加或者创建的对象,继承或者是复制基础对象的属性和方法。factory在提供一系列方法来对这些对象做控制。
  191. factory经过简单的处理可以实现工厂、外观、模板等设计模式。
  192. * @class factory
  193. * @constructor
  194. * @extends klass
  195. * @param {string} name 工厂名称
  196. * @param {object} base 基类对象,所有在工厂中添加的对象都以base为基础
  197. * @param {object} [proto] 工厂的扩展属性和方法对象
  198. * @param {string} [type] 工厂的类型;
  199. * 1. 默认:类实例化后的对象;
  200. * 2. class:类对象,未实例化;
  201. * 3. merge:对象复制合并
  202. * @param {boolean} [initDefault] 是否将base设置成为默认的对象;当使用factory.get找不到对象时返回默认对象
  203. * @return {factory} 返回创建的工厂对象
  204. * @demo test/base/oop.js [factory inheirt] {继承}
  205. * @demo test/base/oop.js [factory class mode] {类继承模式}
  206. * @demo test/base/oop.js [factory merge mode] {对象合并模式}
  207. */
  208. function factory(name, base, proto, type, initDefault) {
  209. var _store = {}, _base = base,
  210. _proto, _type, _initDefault,
  211. args = arguments,
  212. argsLen = args.length,
  213. argType,arg, i = 2,
  214. mergeMode, klassMode, needInit, _defaultItem;
  215.  
  216.  
  217. if(argsLen === 1 && typeof name === 'object'){
  218. _base = name.base;
  219. _proto = name.proto;
  220. _type = name.type;
  221. _initDefault = name.initDefault;
  222. name = name.name;
  223. }
  224. else if (argsLen > i) {
  225. for (; i < argsLen; i++) {
  226. if (arg = args[i]) {
  227. argType = typeof arg;
  228. if (argType === 'object')
  229. _proto = arg;
  230. else if (argType === 'string')
  231. _type = arg;
  232. else if (argType === 'boolean')
  233. _initDefault = arg;
  234. }
  235. }
  236. }
  237.  
  238. if (_type === 'merge')
  239. mergeMode = true;
  240. else if (_type === 'class')
  241. klassMode = true;
  242. else
  243. needInit = true;
  244.  
  245. mergeMode || (_base = klass(name + '_base',_base));
  246.  
  247. //设置默认项
  248. _initDefault && (_defaultItem = needInit ? new _base : _base);
  249.  
  250. /**
  251. 使用工厂创建产品方法,但不注册到factory中
  252. @method build
  253. @param {string} name 产品名称
  254. @param {object} item 产品特性
  255. @param {string} [parent] 父类名称,注册到factory中产品名称
  256. @return {object|klass} 返回创建的产品
  257. @demo test/base/oop.js [factory build]
  258. */
  259. function build(name, item, parent) {
  260. parent = parent ? find(parent) || _base : _base;
  261.  
  262. item._$fType = name;
  263.  
  264. if (mergeMode)
  265. return st.mix(true, item, parent);
  266. else {
  267. item = klass(name, item, parent);
  268. return klassMode ? item : new item;
  269. }
  270. }
  271.  
  272. /**
  273. 添加产品方法,注册到factory中
  274. @method add
  275. @param {string} name 产品名称
  276. @param {object} item 产品特性
  277. @param {string} [parent] 父类名称,注册到factory中产品名称
  278. @return {object|klass} 返回创建的产品
  279. @demo test/base/oop.js [factory add]
  280. */
  281. function add(name, item, parent) {
  282. return (_store[name] = build(name, item, parent));
  283. }
  284.  
  285. /**
  286. 查找注册的产品
  287. @method find
  288. @param {string} name 产品名称
  289. @param {object} defaultMode 是否在找不到产品的时候返回默认产品
  290. @return {object} 返回查找的产品
  291. */
  292. function find(name, defaultMode) {
  293. var obj;
  294. if (arguments.length === 0)
  295. return _defaultItem;
  296.  
  297. if (name && (obj = _store[name])) {
  298. return obj;
  299. }
  300. return defaultMode ? _defaultItem : undefined;
  301. }
  302.  
  303. /**
  304. 将注册的产品设置成默认产品
  305. @method setDefault
  306. @param {string} name 产品名称
  307. @chainable
  308. @demo test/base/oop.js [setDefault]
  309. */
  310. function setDefault(name) {
  311. _defaultItem = find(name, true);
  312. return this;
  313. }
  314.  
  315. /**
  316. 在工厂中移除注册的产品
  317. @method remove
  318. @param {string} name 产品名称
  319. @chainable
  320. */
  321. function remove(name) {
  322. delete _store[name];
  323. }
  324.  
  325. proto = st.mergeObj({
  326. build: build,
  327. add: add,
  328. find: find,
  329. remove: remove,
  330. setDefault: setDefault,
  331. /**
  332. 执行工厂中产品的方法,不会返回结果;当工厂类型为class时,则执行的则是原型链上的方法
  333. @method fire
  334. @param {string} name 方法名称
  335. @param {array} [args] 执行参数
  336. @param {function} [handler] 处理方法
  337. @demo test/base/oop.js [fire]
  338. */
  339. fire : function(name,args,handler){
  340. var fn,result,self = this;
  341. st.each(_store,function(n,item){
  342. if(item){
  343. item.fn && (item = item.fn);
  344. if(fn = item[name])
  345. {
  346. result = fn.apply(item,args);
  347. handler && handler.call(self,item,result);
  348. }
  349. }
  350. })
  351. }
  352. }, _proto);
  353.  
  354. return klass(name, proto, null, {
  355. trigger: true
  356. })();
  357. }
  358.  
  359. return {
  360. klass: klass,
  361. onKlassInit : _onKlassInit,
  362. factory: factory
  363. };
  364. })
Top