factory Class
factory并不只是指的是工厂模式。在factory要求定义一个基础对象,这个对象可以是基类,也可以是模板对象或者是接口。然后factory就已此基础对象为基础,其他添加或者创建的对象,继承或者是复制基础对象的属性和方法。factory在提供一系列方法来对这些对象做控制。 factory经过简单的处理可以实现工厂、外观、模板等设计模式。
Constructor
factory
factory
(
-
name
-
base
-
[proto]
-
[type]
-
[initDefault]
)
Factory
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 工厂名称 | |
base
| Object | 基类对象,所有在工厂中添加的对象都以base为基础 | |
[proto] |
Object | optional | 工厂的扩展属性和方法对象 |
[type] |
String | optional | 工厂的类型;
|
[initDefault] |
Boolean | optional | 是否将base设置成为默认的对象;当使用factory.get找不到对象时返回默认对象 |
Returns:
[Factory]
返回创建的工厂对象
Example:
//一个widget工厂
var widgetFactory = st.factory('wdigetfactory', {
//widget类型
type: '',
//widget的渲染方法
render: function (id) {
return this.type + ':' + id;
}
});
//添加一个input
widgetFactory.add('input', {
type: 'input'
})
//添加一个number类型的input
var num = widgetFactory.add('number', {
type: 'input[number]'
}, 'input')
expect(num.render('txtNum')).toBe("input[number]:txtNum");
var f1 = st.factory({
name: 'classMode',
//设置class类型
type: 'class',
base: {
klassInit: function (name) {
this.name = name;
}
}
});
var c1 = f1.add('c1', {
type: 'c1'
});
expect(c1.fn).toBeDefined
//需要初始化
var c = new c1('class1');
expect(c.type).toBe("c1");
expect(c.name).toBe("class1");
var f2 = st.factory({
name: 'copyMode',
//设置merge类型
type:'merge',
//设置默认模式
initDefault:true,
base:{
name: 'copy',
project :{
name: 'smartjs'
}
}
});
var c = f2.add('c1', {
name: 'c1',
project: {
role: 'pm'
}
});
expect(f2.find.name).toBe("copy");
expect(c.name).toBe("c1");
expect(c.project.name).toBe("smartjs");
expect(c.project.role).toBe("pm");
Methods
add
add
(
-
name
-
item
-
[parent]
)
Object | Klass
添加产品方法,注册到factory中
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 产品名称 | |
item
| Object | 产品特性 | |
[parent] |
String | optional | 父类名称,注册到factory中产品名称 |
Returns:
[Object | Klass]
返回创建的产品
Example:
//widget基类
var baseWidget = {
//widget类型
type: '',
//widget的渲染方法
render: function (id) {
return this.type + ':' + id;
}
};
//一个widget工厂
var widgetFactory = st.factory('wdigetfactory', baseWidget);
//添加一个input
widgetFactory.add('input', {
type: 'input'
})
//找到添加的input
var input = widgetFactory.find('input');
//_$fType为注册的类型名
expect(input._$fType).toBe('input');
//输出
expect(input.render('txt')).toBe("input:txt");
build
build
(
-
name
-
item
-
[parent]
)
Object | Klass
使用工厂创建产品方法,但不注册到factory中
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 产品名称 | |
item
| Object | 产品特性 | |
[parent] |
String | optional | 父类名称,注册到factory中产品名称 |
Returns:
[Object | Klass]
返回创建的产品
Example:
//一个widget工厂
var widgetFactory = st.factory('wdigetfactory', {
//widget类型
type: '',
//widget的渲染方法
render: function (id) {
return this.type + ':' + id;
}
}, 'class');
var Tab = widgetFactory.build('Tab', {type: 'Tab'});
expect(widgetFactory.find('Tab')).toBeUndefined
var tab1 = new Tab;
expect(tab1.render('tab1')).toBe('Tab:tab1');
callBase
callBase
(
-
fnName
-
[baseName]
-
[args]
)
Object
调用基类的方法
Parameters:
name | type | flag | description |
---|---|---|---|
fnName
| String | 方法名称 | |
[baseName] |
String | optional | 基类名称 |
[args] |
Array | optional | 方法参数数组 |
Returns:
[Object]
执行结果
Example:
var Animate = st.klass("Animate", {
klassInit: function (name) {
this.name = name;
},
say: function (text) {
return this.name + ':' + text;
}
});
//继承user
var Bird = st.klass("Bird", {
//重写say方法
say: function (text) {
//调用基类方法
return '[Bird]' + this.callBase('say', [text]);
}
}, Animate);
var chicken = new Bird('chicken');
expect(chicken.say('hello')).toBe('[Bird]chicken:hello');
//创建一个class
var User = st.klass('user', {
klassInit: function (name) {
this.name = name;
},
say: function (text) {
return this.name + ',' + text;
}
});
//实例化一个User
var xiaoming = new User('小明');
//方法实例化
var xiaozhang = User('小张');
//多级继承例子。在多级继承中有一种场景每个子类方法都会调用父类的方法,而方法中又会使用到当前对象的属性,则问题就来了;
//如果是采用的parent.xxx然后传递this下的属性值过去,则没太大的问题。backbone就采用的这种。
//另外像base.js直接改写原始方法,将父对象封入闭包中,也无问题。只是这种限制比较大,只能调用父类的同名方法。
//而dojo采用的是this.parent.xxx.call(this)的方式,则就会悲剧了,死循环就来了。
//导致这样的原因就是将this带入parent方法后,父类又执行this.parent。而这是this则是子类的对象,那么方法就只会不停的调用parent的方法。
//在smartjs中klass调用父类方法由callBae这个方法来代理,同时使用指针来记录方法的执行轨迹,这样保证了从子到根的各级调用
var user2 = st.klass('user2', {
say: function (text) {
//调用父类
return this.callBase('say', [text]) + "-lv2";
}
}, User);
var user3 = st.klass('user3', {
say: function (text) {
//调用父类
return this.callBase('say', [text]) + "-lv3";
}
}, user2);
var user4 = st.klass('user4', {
say: function (text) {
//调用父类
return this.callBase('say', [text]) + "-lv4";
}
}, user3);
var roy = new user4('roy');
//继承路径
expect(roy._$inheirts + '').toBe('user4,user3,user2,user');
//依次执行到根,正确将当前的this对象的值输出
expect(roy.say('hello')).toBe('roy,hello-lv2-lv3-lv4');
//从3级开始执行
expect(roy.callBase('say', ['hello'])).toBe("roy,hello-lv2-lv3");
//指定从user开始执行
expect(roy.callBase('say', 'user', ['hello'])).toBe("roy,hello");
//上向略过2级执行
expect(roy.callBase('say', 2, ['hello'])).toBe("roy,hello-lv2");
callProto
callProto
(
-
name
-
[args]
)
调用原型链方法
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 需要执行的原型链方法名 | |
[args] |
Array | optional | 执行参数 |
Returns:
[object] 返回执行结果
Example:
var Animate = st.klass("Animate", {
klassInit: function (name) {
this.name = name;
},
say: function (text) {
return this.name + ':' + text;
}
});
var chicken = new Animate('chicken');
chicken.say = function (text) {
//调用原型链方法
return '[Bird]' + this.callProto('say', [text]);
};
expect(chicken.say('hello')).toBe('[Bird]chicken:hello');
extend
extend
(
-
prop
)
chainable
类扩展方法
Parameters:
name | type | flag | description |
---|---|---|---|
prop
| Object | 扩展的属性和方法对象 |
Example:
var Animate = st.klass("Animate", {
klassInit: function (name) {
this.name = name;
},
say: function (text) {
return this.name + ':' + text;
}
});
var chicken = new Animate('chicken');
//扩展等同于 chicken.say = xxx
chicken.extend({
say: function (text) {
return 'hello';
}
});
expect(chicken.say('hello')).toBe('hello');
find
find
(
-
name
-
defaultMode
)
Object
查找注册的产品
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 产品名称 | |
defaultMode
| Object | 是否在找不到产品的时候返回默认产品 |
Returns:
[Object]
返回查找的产品
fire
fire
(
-
name
-
[args]
-
[handler]
)
执行工厂中产品的方法,不会返回结果;当工厂类型为class时,则执行的则是原型链上的方法
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 方法名称 | |
[args] |
Array | optional | 执行参数 |
[handler] |
Function | optional | 处理方法 |
Example:
var widgetFactory = st.factory('wdigetfactory', {
type: '',
render: function (id) {
return this.type + ':' + id;
}
});
widgetFactory.add('Panel', {
type: 'Panel'
});
widgetFactory.add('Tab', {
type: 'Tab'
});
var ret = '';
//执行每个widget的render方法;
widgetFactory.fire('render', ['id'], function (item, result) {
//this为widgetFactory;item为产品;result为render执行结果
ret += result + '-';
})
expect(ret).toBe('Panel:id-Tab:id-');
getBase
getBase
(
-
[baseName]
)
获取基类对象
Parameters:
name | type | flag | description |
---|---|---|---|
[baseName] |
String | optional | 基类名称,不设置则返回父类 |
Returns:
[object] 返回基类
Example:
var Animate = st.klass("Animate", {
klassInit: function (name) {
this.name = name;
},
say: function (text) {
return this.name + ':' + text;
}
});
//继承user
var Bird = st.klass("Bird", {
//重写say方法
say: function (text) {
//根据名称向上找到父类原型
var parent = this.getBase('Animate');
//调用原型链方法
return '[Bird]' + parent.say.call(this, text);
}
}, Animate);
var chicken = new Bird('chicken');
expect(chicken.say('hello')).toBe('[Bird]chicken:hello');
remove
remove
(
-
name
)
chainable
在工厂中移除注册的产品
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 产品名称 |
setDefault
setDefault
(
-
name
)
chainable
将注册的产品设置成默认产品
Parameters:
name | type | flag | description |
---|---|---|---|
name
| String | 产品名称 |
Example:
//一个widget工厂
var widgetFactory = st.factory({
//工厂名
name: 'wdigetfactory',
//工厂类型
type: 'class',
//基类对象
base: {
//widget类型
type: '',
//widget的渲染方法
render: function (id) {
return this.type + ':' + id;
}
}
});
widgetFactory.add('Panel', {type: 'Panel'});
//将Panel设置成默认项
widgetFactory.setDefault('Panel')
//Tab未注册,但参数中设置了返回默认,则会返回Panel
var Tab = widgetFactory.find('Tab', true);
var tab1 = new Tab
expect(tab1.render('tab1')).toBe('Panel:tab1');