"use strict";
/**
面向对象思想的辅助实现模块;
Feartures :
1. klass :类继承;实现执行指针,类常用方法,继承路径
2. factory :对象/类工厂方法;
Update Note:
+ 2014.6 :Created
@module OOP
*/
_stDefine('oop', function(st) {
//初始化扩展函数
var _onKlassInit = st.promiseEvent(),
/**
* klass的基类对象
* @class klassBase
*/
_klassBase = {
/**
调用原型链方法
@method callProto
@param name {string} 需要执行的原型链方法名
@param [args] {array} 执行参数
@return [object] 返回执行结果
@demo test/base/oop.js [klassBase - callProto] {执行原型链方法}
*/
callProto : function(name,args){
var fn = this._$fn[name];
if(fn)
return fn.apply(this,args);
},
/**
获取基类对象
@method getBase
@param [baseName] {string} 基类名称,不设置则返回父类
@return [object] 返回基类
@demo test/base/oop.js [klassBase - getBase] {获取基类对象}
*/
getBase: function(baseName) {
var self = this,
parent = self._$super;
if (baseName && typeof baseName == 'number')
baseName = self._$inheirts[baseName];
if (parent) {
if (baseName) {
while (parent && parent._$kName != baseName) {
parent = parent._$super;
}
} else if (parent._$kName == self._$kName) {
return null;
}
}
return parent;
},
/**
调用基类的方法
@method callBase
@param {string} fnName 方法名称
@param {string} [baseName] 基类名称
@param {array} [args] 方法参数数组
@return {object} 执行结果
@demo test/base/oop.js [klassBase - callBase] {调用父类}
@demo test/base/oop.js [muilt heirht - callBase] {多级继承示例}
*/
callBase: function(fnName, baseName, args) {
var self = this,
base = self._$super,
fn, result, current, indicator = self._$indicator;
if (!base)
return;
if (arguments.length < 3) {
args = baseName;
baseName = null;
}
if (baseName)
base = self.getBase(baseName);
else if (current = indicator[fnName])
base = current._$super || current.fn._$super || current;
if (base && (fn = base[fnName])) {
indicator[fnName] = base;
result = fn.apply(this, args);
indicator[fnName] = null;
}
return result;
},
/**
类扩展方法
@method extend
@param {object} prop 扩展的属性和方法对象
@chainable
@demo test/base/oop.js [klassBase - extend] {类扩展}
*/
extend: function(prop) {
st.mergeObj(this, prop);
return this;
}
};
st.conf('oop-KlassBase',_klassBase);
/**
js类创建,具有执行指针功能(解决了多级继承域对象的问题)
此外提供两种全局扩展方式:
1. 基于原形链的基类扩展,使用st.conf('oop-KlassBase'),可以取到基类对象进行扩展
2. 在类初始化时,对实例化的对象进行扩展,可以使用st.onKlassInit对象进行添加扩展方法。st.onKlassInit 是promiseEvent对象,st.onKlassInit(obj,config);
@class klass
@constructor
@extend klassBase
@param {string} name 类名称
@param {object} prop 类的属性和方法
@param {klass|object|function} [parent] 父类
@param {object} [config] 扩展参数
@return {klass} 返回类
@demo test/base/oop.js [class init] {实例化}
@demo test/base/oop.js [inheirt] {类继承}
@demo test/base/oop.js [klass prop check] {继承特性检查}
@demo test/base/oop.js [muilt heirht - callBase] {多级继承}
*/
function klass(name, prop, parent, config) {
var _super, _proto, _prop = prop,
_inheirts = [name],
_obj = function() {
var self = this,
args = arguments,
len = args.length;
//自执行初始化判断
if (!(self instanceof _obj)) {
if (len === 0)
return new _obj();
if (len < 4)
return new _obj(args[0], args[1], args[2]);
else if (len < 7)
return new _obj(args[0], args[1], args[2], args[3], args[4], args[5]);
else
return new _obj(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
}
//设置指针对象
self._$indicator = {};
//设置原型链
self._$fn = _proto;
//执行扩展方法
_onKlassInit.fireWith(self,config);
//klassInit默认初始化
self.klassInit && self.klassInit.apply(self, args);
}
if (parent) {
_super = parent.prototype || parent;
_proto = _obj.prototype = Object.create(_super);
_proto._$super = _super;
_proto.constructor = parent;
//添加父的继承路径
if (_super._$inheirts)
_inheirts = _inheirts.concat(_super._$inheirts);
else
_inheirts.push(parent.name);
} else
_proto = st.mergeObj(_obj.prototype, _klassBase);
_obj.fn = _proto;
st.mergeMulti([_proto, _prop,{
//类标示
_$klass: true,
//类名
_$kName: name,
//继承链
_$inheirts: _inheirts
}]);
return _obj;
}
// _onKlassInit.add('attachTrigger', function(config) {
// var trigger = config.trigger;
// trigger && st.attachTrigger(this, trigger.iFace, trigger.mode);
// })
/**
* factory并不只是指的是工厂模式。在factory要求定义一个基础对象,这个对象可以是基类,也可以是模板对象或者是接口。然后factory就已此基础对象为基础,其他添加或者创建的对象,继承或者是复制基础对象的属性和方法。factory在提供一系列方法来对这些对象做控制。
factory经过简单的处理可以实现工厂、外观、模板等设计模式。
* @class factory
* @constructor
* @extends klass
* @param {string} name 工厂名称
* @param {object} base 基类对象,所有在工厂中添加的对象都以base为基础
* @param {object} [proto] 工厂的扩展属性和方法对象
* @param {string} [type] 工厂的类型;
* 1. 默认:类实例化后的对象;
* 2. class:类对象,未实例化;
* 3. merge:对象复制合并
* @param {boolean} [initDefault] 是否将base设置成为默认的对象;当使用factory.get找不到对象时返回默认对象
* @return {factory} 返回创建的工厂对象
* @demo test/base/oop.js [factory inheirt] {继承}
* @demo test/base/oop.js [factory class mode] {类继承模式}
* @demo test/base/oop.js [factory merge mode] {对象合并模式}
*/
function factory(name, base, proto, type, initDefault) {
var _store = {}, _base = base,
_proto, _type, _initDefault,
args = arguments,
argsLen = args.length,
argType,arg, i = 2,
mergeMode, klassMode, needInit, _defaultItem;
if(argsLen === 1 && typeof name === 'object'){
_base = name.base;
_proto = name.proto;
_type = name.type;
_initDefault = name.initDefault;
name = name.name;
}
else if (argsLen > i) {
for (; i < argsLen; i++) {
if (arg = args[i]) {
argType = typeof arg;
if (argType === 'object')
_proto = arg;
else if (argType === 'string')
_type = arg;
else if (argType === 'boolean')
_initDefault = arg;
}
}
}
if (_type === 'merge')
mergeMode = true;
else if (_type === 'class')
klassMode = true;
else
needInit = true;
mergeMode || (_base = klass(name + '_base',_base));
//设置默认项
_initDefault && (_defaultItem = needInit ? new _base : _base);
/**
使用工厂创建产品方法,但不注册到factory中
@method build
@param {string} name 产品名称
@param {object} item 产品特性
@param {string} [parent] 父类名称,注册到factory中产品名称
@return {object|klass} 返回创建的产品
@demo test/base/oop.js [factory build]
*/
function build(name, item, parent) {
parent = parent ? find(parent) || _base : _base;
item._$fType = name;
if (mergeMode)
return st.mix(true, item, parent);
else {
item = klass(name, item, parent);
return klassMode ? item : new item;
}
}
/**
添加产品方法,注册到factory中
@method add
@param {string} name 产品名称
@param {object} item 产品特性
@param {string} [parent] 父类名称,注册到factory中产品名称
@return {object|klass} 返回创建的产品
@demo test/base/oop.js [factory add]
*/
function add(name, item, parent) {
return (_store[name] = build(name, item, parent));
}
/**
查找注册的产品
@method find
@param {string} name 产品名称
@param {object} defaultMode 是否在找不到产品的时候返回默认产品
@return {object} 返回查找的产品
*/
function find(name, defaultMode) {
var obj;
if (arguments.length === 0)
return _defaultItem;
if (name && (obj = _store[name])) {
return obj;
}
return defaultMode ? _defaultItem : undefined;
}
/**
将注册的产品设置成默认产品
@method setDefault
@param {string} name 产品名称
@chainable
@demo test/base/oop.js [setDefault]
*/
function setDefault(name) {
_defaultItem = find(name, true);
return this;
}
/**
在工厂中移除注册的产品
@method remove
@param {string} name 产品名称
@chainable
*/
function remove(name) {
delete _store[name];
}
proto = st.mergeObj({
build: build,
add: add,
find: find,
remove: remove,
setDefault: setDefault,
/**
执行工厂中产品的方法,不会返回结果;当工厂类型为class时,则执行的则是原型链上的方法
@method fire
@param {string} name 方法名称
@param {array} [args] 执行参数
@param {function} [handler] 处理方法
@demo test/base/oop.js [fire]
*/
fire : function(name,args,handler){
var fn,result,self = this;
st.each(_store,function(n,item){
if(item){
item.fn && (item = item.fn);
if(fn = item[name])
{
result = fn.apply(item,args);
handler && handler.call(self,item,result);
}
}
})
}
}, _proto);
return klass(name, proto, null, {
trigger: true
})();
}
return {
klass: klass,
onKlassInit : _onKlassInit,
factory: factory
};
})