单元测试与设计模式(3)
正文
设计模式:
/**
* [Decorator]
* 装饰者模式
*在不改变源对象的基础上,通过对其进行包装扩展(添加属性或者方法)使原有对象能够满足用户的更发杂的需求。
*/
Decorator:function(name){
var result = "";
var linshui = {
Util : {
testA : function(){
result = "linshui";
}
}
}
//装饰者
var decorator = function(fn){
//如果事件源存在
console.log(typeof linshui.Util[fn]);
if(typeof linshui.Util[fn] === 'function'){
//缓存事件原有回调函数
var oldFn = linshui.Util[fn];
function zhaoying(){
result += "zhaoying";
}
//执行原有回调函数
oldFn();
//执行新增的回调函数
zhaoying();
}else{
result = "new function";
}
}
decorator(name);
return result;
},
/**
* [Observer]
* 观察者模式
* 又称为发布-订阅者模式或者消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合。
*/
Observer:function(type,msg){
//将观察着放在闭包,立即调用
var Observer = (function(){
//防止消息队列暴漏而被篡改因此将消息容器作为静态私有变量保存
var _messages = {};
return {
//订阅消息方法
regist : function(type,fn){
//如果此消息不存在则创建一个该消息类型
if(typeof _messages[type] === 'undefined'){
_messages[type] = [fn];
}else{
//将动作方法推入该消息对应的动作执行序列中
_messages[type].push(fn);
}
},
//发布消息方法
fire : function(type,args){
//如果该类消息没有被注册则返回
if(!_messages[type])
return;
var events = {
type : type, //消息类型
args : args || {} //消息携带数据
},
i = 0, //消息动作循环变量
len = _messages[type].length; //消息动作长度
//遍历消息
for(; i < len ;i++){
//依次执行注册的消息对应的动作序列
_messages[type][i].call(this,events);
}
},
//取消订阅方法
remove : function(type,fn){
//如果消息动作队列存在
if(_messages[type] instanceof Array){
//从最后一个动作遍历
var i = _messages[type].length - 1;
for (; i > 0; i--) {
//如果存在该动作则在消息动作序列中移除相应动作
_messages[type][i] === fn && _messages[type].splice(i,1);
};
}
}
}
})();
var result;
console.log(Observer);
Observer.regist(type,function(e){
result = e.args.msg+"2333";
});
Observer.fire(type,{msg:msg});
return result;
}
单元测试:
it('对装饰者模式正向测试,返回值应该是linshuizhaoying', function() {
var defaultData = myComponent;
defaultData.methods.Decorator("testA").should.be.eql("linshuizhaoying");
});
it('对装饰者模式正向测试,返回值应该是linshuizhaoying', function() {
var defaultData = myComponent;
defaultData.methods.Decorator("testB").should.be.eql("new function");
});
it('对观察者模式正向测试,返回值应该是linshuizhaoying', function() {
var defaultData = myComponent;
defaultData.methods.Observer("linshui","linshuizhaoying").should.be.eql("linshuizhaoying2333");
});