视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript责任链模式介绍
2020-11-27 20:11:46 责编:小采
文档
介绍

责任链模式(Chain of responsibility)是使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

请求以后,从第一个对象开始,链中收到请求的对象要么亲自处理它,要么转发给链中的下一个候选者。提交请求的对象并不知道哪一个对象将会处理它——也就是该请求有一个隐式的接受者(implicit receiver)。在运行时,任一候选者都可以响应相应的请求,候选者的数目是任意的,也可以在运行时刻决定哪些候选者参与到链中。

图解为:

正文

(1)由于类一般是与接口打交道的,为此我们先定义一个规范类中方法的接口,代码为

 //定义一个静态方法来实现接口与实现类的直接检验
//静态方法不要写出Interface.prototype ,因为这是写到接口的原型链上的
//我们要把静态的函数直接写到类层次上
//定义一个接口类
var Interface=function (name,methods) {//name:接口名字
 if(arguments.length<2){
 alert("必须是两个参数")
 }
 this.name=name;
 this.methods=[];//定义一个空数组装载函数名
 for(var i=0;i<methods.length;i++){
 if(typeof methods[i]!="string"){
 alert("函数名必须是字符串类型");
 }else {
 this.methods.push( methods[i]);
 }
 }
};
Interface.ensureImplement=function (object) {
 if(arguments.length<2){
 throw new Error("参数必须不少于2个")
 return false;
 }
 for(var i=1;i<arguments.length;i++){
 var inter=arguments[i];
 //如果是接口就必须是Interface类型
 if(inter.constructor!=Interface){
 throw new Error("如果是接口类的话,就必须是Interface类型");
 }
 //判断接口中的方法是否全部实现
 //遍历函数集合分析
 for(var j=0;j<inter.methods.length;j++){
 var method=inter.methods[j];//接口中所有函数
 //object[method]传入的函数
 //最终是判断传入的函数是否与接口中所用函数匹配
 if(!object[method]||typeof object[method]!="function" ){//实现类中必须有方法名字与接口中所用方法名相同
 throw new Error("实现类中没有完全实现接口中的所有方法")
 }
 }
 }
}

(2)使用定义一个书店的接口

var bookShop=new Interface("bookShop",["addBook","findBook","showBooks"]);//书店接口

(3)定义一个书类

var Book=function (bNm,bName,bAuthor,bType) {
 this.bNm=bNm;
 this.bName=bName;
 this.bAuthor=bAuthor;
 this.bType=bType;
}

(4)书店类=书架+图书

#1:在书店中添加书架和图书

var pcatBookShop=(function(){

 //书架
 var jsBooks = new Array();//js书架
 var cBooks = new Array();//c书架
 var javaBooks = new Array();//java书架
 //内部类1
 function AddJsBooks(book) {
 if(book.bType=="Js"){
 jsBooks.push(book);
 }else {
 AddJsBooks.successor(book);
 }
 }
 //内部类2
 function AddJavaBooks(book) {
 if(book.bType=="Java"){
 javaBooks.push(book);
 }else {
 AddJavaBooks.successor(book);
 }
 }
 //内部类3
 function AddCBooks(book) {
 if(book.bType=="C"){
 cBooks.push(book);
 }else {
 AddCBooks.successor(book);
 }
 }

})()

#2:扩展设置责任链的方法(扩展在windows上)

//扩展window属性window.setSuccessor=function (after,before) {
 after.successor=before;//引用的执行}

#3:设置责任链,将每个对象链接起来

 //设置责任链-----串起来 
 setSuccessor(AddJsBooks,AddJavaBooks);
 setSuccessor(AddJavaBooks,AddCBooks);

(5)查询图书的方法:通过图书编号和图书图书名称

/**********查询书籍************/
 var bookList = null;
 function FindBbn(keyword) {
 //链的头部来初始化参数
 if(!bookList){
 bookList=jsBooks.concat(cBooks).concat(javaBooks);
 var book = new Array();
 book=bookList.filter(function (book) {//对booklist进行过滤,过滤的条件为匿名函数
 if(book.bName.indexOf(keyword)!=-1){
 return true;
 }else {
 return false;
 }
 });
 //我要进行链式查询
 return book.concat(FindBbn.successor(keyword));
 }
 };
 function FindByName(keyword,book){
 var book = book;
 book = bookList.filter(function(book){
 if(book.bName.indexOf(keyword) != -1){
 return true;
 }else{
 return false;
 }
 });
 return book;
 }

注意,数组的filter方法扩展代码如下

Function.prototype.method=function (name,fn) {
 this.prototype[name]=fn;
 return this;
}
if(!Array.prototype.filter){
 Array.method("filter",function (fn,thisObj) {
 var scope=thisObj||window;
 var a=[];
 for(var i=0;i<this.length;i++){
 if(!fn.call(scope,this[i],i,this));{
 continue;
 }
 a.push(this[i]);
 }
 //返回过滤好数据
 return a;
 })
}

(6)规划责任链

 setSuccessor(FindBbn,FindByName);

(7)真正的书店类(实现接口的类)

return function () {
 this.addBook=function (book) {
 if(book instanceof Book){
 AddJsBooks(book);//因为我知道谁是链的入口
 }
 };
 this.findBook=function (keyword) {
 return FindBbn(keyword);//游泳规划的责任链可以从头到尾的查询若,FindBbn没有则到FindByName中查询
 }
 this.showBooks=function () {
 document.write("JS类图书"+jsBooks.toSource()+"<br>");
 document.write("Java类图书"+javaBooks.toSource()+"<br>");
 document.write("C类图书"+cBooks.toSource()+"<br>");
 //自动生产----------
 document.write(cpoyStr(60,"-")+"<br>");
 }
 }

注意,在window上扩展一个可以自动生成“---------------”的方法

//扩展一个可以自动生产-----的方法
window.cpoyStr=function (num,str) {
 var newStr="";
 for(var i=0;i<num;i++){
 newStr+=str;
 }
 return newStr;
};

(8)使用书店

#1:添加书

 var pb = new pcatBookShop();
 pb.addBook(new Book("00101","JAVA","JIM","JAVA"));
 pb.addBook(new Book("00201","C#","world","C"));
 pb.addBook(new Book("00202","C++/C","Hello","C"));
 pb.addBook(new Book("00301","JAVASCRIPT","Good","JS"));

#2:对书架上的书进行操作-----展示

//展示 pb.showBooks();
 document.write(pb.findBook("C").toSource())

为此我们基本上完成了对责任链模式的使用方式的基本学习。

下载本文
显示全文
专题