怎么查询网站备案接入商,国内做的好的电商网站有哪些,网站建设 今网科技,济南网络推广公司哪家好前言 博客园谈设计模式的文章很多#xff0c;我也受益匪浅#xff0c;包括TerryLee、吕震宇等等的.NET设计模式系列文章#xff0c;强烈推荐。对于我#xff0c;擅长于前台代码的开发#xff0c;对于设计模式也有一定的了解#xff0c;于是我想结合Javascript来设计前台方…前言 博客园谈设计模式的文章很多我也受益匪浅包括TerryLee、吕震宇等等的.NET设计模式系列文章强烈推荐。对于我擅长于前台代码的开发对于设计模式也有一定的了解于是我想结合Javascript来设计前台方面的“设计模式”以对后台“设计模式”做个补充。开始这个系列我也诚惶诚恐怕自己写得不好不过我也想做个尝试一来希望能给一些人有些帮助吧二来从写文章中锻炼下自己三来通过写文章对自己增加自信如果写得不好欢迎拍砖我会虚心向博客园高手牛人们学习请教如果觉得写得还可以谢谢大家的支持了:) 这篇将介绍观察者模式。 概述 在现实生活中存在着“通知依赖关系”如在报纸订阅的服务只要读者订阅者订购了《程序员》的期刊杂志那么他就订阅了这个服务他时刻“监听”着邮递员出版者来投递报纸给他们而邮递员出版者只要报社有新刊杂志传达给他就是状态发生了变化邮递员出版者就随时投递通知订阅了服务的读者另一方面如果读者不想在继续订购取消通知《程序员》的杂志了那么邮递员就不在投递通知这些读者了。这就是典型的出版者和订阅者的关系而这个关系用一个公式来概括 出版者 订阅者 观察者模式 定义 观察者模式定义了对象之间的一对多依赖这样一来当一个对象改变状态时他的所有依赖者都会收到通知并自动更新。 类图 示例分析 现在开始利用观察者模式来应用到项目的一个场景中去并且层层剖析一下。 有这样一个场景一个购书网站用户提交上去一个订单网站系统只要有订单上来会采取如下操作为了简化我这里其实只是简单的提交 一、产生一条通知用户“已购买”记录的短信息该短信箱还会有其他记录如交友等等 二、在浏览器上显示你的订单名片 三、该条订单提交上服务器保存到数据库或者其它任何存储介质中去最后显示你的购书记录 那么开始我的设计 1. 网站上添加IPublisher.js它作为系统的出版者“接口”利用第0篇文章面向对象基础以及接口和继承类的实现中的Interface.js类另外谢谢winter-cn园友提出了些宝贵的建议目前Interface类还在改善中这里暂且先用原来的Interface类 这里是改进的程序示范包括重载函数的构造这里也暂时贴出来下 改进的代码改进的代码// Interface.jsfunction Interface(name, methods) { if(arguments.length ! 2) { throw new Error(接口构造函数含 arguments.length 个参数, 但需要2个参数.); } this.name name; this.methods []; if(methods.length 1) { throw new Error(第二个参数为空数组.); } for(var i 0, len methods.length; i len; i) { if(typeof methods[i][0] ! string) { throw new Error(接口构造函数第一个参数必须为字符串类型.); } for(var j 1; j methods[i].length; j) { if(methods[i][j] typeof methods[i][j] ! number) { throw new Error(接口构造函数第二个参数以上必须为整数类型.); } } this.methods.push(methods[i]); } }; Interface.registerImplements function(object) { if(arguments.length 2) { throw new Error(接口的实现必须包含至少2个参数.); } for(var i 1, len arguments.length; i len; i) { var interface arguments[i]; if(interface.constructor ! Interface) { throw new Error(从第2个以上的参数必须为接口实例.); } for(var j 0, methodsLen interface.methods.length; j methodsLen; j) { var method1 interface.methods[j][0]; var arr1 interface.methods[j].slice(1).sort(compareNumber); for(var k 0; k object.methodArr.length; k) { var method2 object.methodArr[k][0]; if(method1 method2) { var arr2 object.methodArr[k].slice(1).sort(); if(ComareArray(arr1,arr2)) { break; } else { throw new Error(接口的实现对象不能执行 interface.name 的接口方法 method1 因为它找不到或者不匹配.); } } } } } };function compareNumber(num1, num2) { var iNum1 parseInt(num1); var iNum2 parseInt(num2); if(iNum1 iNum2) return -1; else if(iNum1 iNum2) return 1; else return 0; }function ComareArray(arr1, arr2) { if(arr1.length!arr2.length) { return false; } for(var i 0; i arr1.length; i) { if(arr1[i]!arr2[i]) { return false; } } return true; } Function.prototype.getParameters function() { var str this.toString(); var paramString str.slice(str.indexOf(() 1, str.indexOf())).replace(/\s*/g,); //取得参数字符串 try { return (paramString.length 0 ? [] : paramString.split(,)); } catch(err) { throw new Error(函数不合法!); } }// demo.js function Overload(method) { this.methods []; for(var i 1; i arguments.length - 1; i) { methods.push(arguments[i].length); } OverloadNumber.methodArr.push([arguments[0]].concat(methods)); OverloadNumber.argumentArr.push(arguments); return function() { for(var i 0; i OverloadNumber.methodArr.length; i) { if(OverloadNumber.methodArr[i][0] method) { var index OverloadNumber.methodArr[i].slice(1).indexOf(arguments.length); if(index ! -1) { return OverloadNumber.argumentArr[i][index1].apply(this,arguments); } } } throw new Error(参数不匹配!); } }var INumber new Interface(INumber, [[Add,1,0,2,3],[Sub,1,2]]); //其中1,0,2,3之类属于重载函数参数个数可以不按先后顺序function OverloadNumber() { Interface.registerImplements(OverloadNumber, INumber); } OverloadNumber.methodArr []; OverloadNumber.argumentArr []; OverloadNumber.prototype { Add : Overload( //算术加 Add, function(a,b) { return a b; }, function(a) { return a; }, function(a,b,c) { return abc; }, function() { return -1; } ), Sub : Overload( //算术减 Sub, function(a) { return --a; }, function(a,b) { return a - b; } ) } 调用如下 调用方法var number new OverloadNumber(); alert(4 - 1 number.Sub(4,1)); alert(3 number.Add(3)); alert(4 6 number.Add(4, 6)); alert(4 6 5 number.Add(4, 6, 5)); alert(number.Add()); alert(3 - 1 number.Sub(3,1)); alert(--10 number.Sub(10)); alert(number.Add(4, 6, 5, 9)); // Error参数不匹配 var IPublisher new Interface(IPublisher, [[registerSubscriber,1], [removeSubscriber,1], [notifySubscribers]]); 所有的依赖者订阅者将要注册于它的实现类。 2. 添加ISubscriber.js它作为系统的订阅者“接口” var ISubscriber new Interface(ISubscriber,[[update,4]]); 3. 现在开始实现我们的IPublisher的具体类添加OrderData.js它作为一个订单数据类让其继承IPublisher的接口 function OrderData() { this._subscribers new Array(); //观察者列表 this.ProductName ; //商品名称 this.ProductPrice 0.0; //商品价格 this.Recommend 0; //推荐指数 this.productCount 0; //购买个数 Interface.registerImplements(this, IPublisher); } OrderData.prototype { registerSubscriber : function(subscriber) { //注册订阅者 this._subscribers.push(subscriber); }, removeSubscriber : function(subscriber) { //删除指定订阅者 var i _subscribers.indexOf(subscriber); if(i 0) _subscribers.slice(i,1); }, notifySubscribers : function() { //通知各个订阅者 for(var i 0; i this._subscribers.length; i) { this._subscribers[i].update(this.ProductName, this.ProductPrice, this.Recommend, this.ProductCount); } }, SubmitOrder : function(productName,productPrice,recommend,productCount) { //提交订单 this.ProductName productName; this.ProductPrice productPrice; this.Recommend recommend; this.ProductCount productCount; this.notifySubscribers(); } } 这里简单介绍下OrderData构造函数中设置订阅者列表以及商品属性 Interface.registerImplements(this, IPublisher); 实际上是让OrderData继承IPublisher接口 registerSubscriberremoveSubscribernotifySubscribers实际上覆盖了从IPublisher继承上来的“接口”方法这样保存了这个类的方法调用其中notifySubscribers为通知所有的订阅者更新信息 4. 实现ISubscriber的具体类添加Subscriber.js它里面包含三个订阅者1MsgBox类短信箱列表2ThisOrder类该条订单名片3OrderList类我的订单列表并且让其三都继承ISubscriber的“接口” function MsgBox(publisher) { this.Publisher publisher; this.Publisher.registerSubscriber(this); Interface.registerImplements(this, ISubscriber); } MsgBox.prototype.update function(productName,productPrice,recommend,productCount) {// 具体实现} function ThisOrder(publisher) { this.Publisher publisher; this.Publisher.registerPublisher(this); Interface.registerImplements(this, ISubscriber); } ThisOrder.prototype.update function(productName,productPrice,recommend,productCount) { // 具体实现} function OrderList(publisher) { this.Publisher publisher; this.Publisher.registerPublisher(this); Interface.registerImplements(this, ISubscriber); } OrderList.prototype.update function(productName,productPrice,recommend,productCount) { // 具体实现} 看到Subscriber实现类们的构造函数中的内容了么它把出版者类参数赋值于Subscriber实现类们的Publisher对象然后在该对象上注册this订阅者自己这样Publisher对象上就注册了Subscriber对象并且以Array对象的方式存储起来 5. 好了IPublisher.jsISubscriber.jsOrderData.jsSubscriber.js都创建好了现在需要一个aspx界面来使用它们了 div idContainer table width600px cellpadding0 cellspacing1 classgrid thead tr th 商品名 /th th 市场价 /th th 推荐指数 /th th 数量 /th /tr /thead tbody tr td span idproductName你必须知道的.NET/span /td td aligncenter span idproductPrice69.8/span /td td aligncenter span idrecommend10/span /td td aligncenter span idproductCount1/span /td /tr /tbody tfoot tr td alignright colspan4 input typebutton idbtnSubmit value 结 算 / /td /tr /tfoot /table/divdiv stylewidth: 1000px; div idMsgBoxContainer h2 您的短信箱/h2 table width100% cellspacing1 cellpadding0 classgrid thead tr th 内容 /th th stylewidth: 100px; 发布日期 /th /tr /thead tbody idMsgBoxResult /tbody /table /div div idThisOrderContainer h2 您刚提交的订单名片/h2 div idThisOrderResult /div /div div idOrderListContainer h2 您已买的商品列表/h2 table width100% cellspacing1 cellpadding0 classgrid thead tr th 商品名 /th th 市场价 /th th 推荐指数 /th th 数量 /th th stylewidth: 100px; 发布日期 /th /tr /thead tbody idOrderListResult /tbody /table /div div classclear /div/div 6. 创建一个OrderSend.js编写相关的JS代码了以下是核心代码 $(#btnSubmit).click(function(){ var productName $(#productName).html(); var productPrice parseFloat($(#productPrice).html()); var recommend parseInt($(#recommend).html()); var productCount parseInt($(#productCount).html()); var orderData new OrderData(); //实例化Publisher的实现类orderData var msgBox new MsgBox(orderData); //orderData作为MsgBox构造函数的参数进行传递 var thisOrder new ThisOrder(orderData); //orderData作为ThisOrder构造函数的参数进行传递 var orderList new OrderList(orderData); //orderData作为OrderList构造函数的参数进行传递 orderData.SubmitOrder(productName,productPrice,recommend,productCount); //提交相关商品信息}); 通过点击页面上的“提交”将三个Subscriber实现类注册到OrderData(Publisher实现类)中去这样只要OrderData对象提交新商品信息上去也就是状态更新那么三个Subscriber实现类就会被通知而更新自身相关的内容了。 页面实现效果如下 点击“结算”按钮如下 这里只是简单的对于三个Subscriber进行更新关于update方法中的实现这里不在贴出来了具体可以下载源代码查看看在update方法中可以编写你想要的操作以及显示结果如利用$.ajax进行数据操作和数据展示这里就留着大家自己发挥吧:) 总结 该篇文章用Javascript来设计观察者模式的思路通过触发变化通知的方式来请求状态更新利用一个简单的购书网站来实践。 本篇到此为止谢谢大家阅读 附相关源代码下载 参考文献《Head First Design Pattern》 本系列文章转载时请注明出处谢谢合作 相关系列文章Javascript乱弹设计模式系列(6) 单件模式(Singleton)Javascript乱弹设计模式系列(5) 命令模式(Command)Javascript乱弹设计模式系列(4) 组合模式(Composite)Javascript乱弹设计模式系列(3) 装饰者模式(Decorator)Javascript乱弹设计模式系列(2) 抽象工厂以及工厂方法模式(Factory)Javascript乱弹设计模式系列(1) 观察者模式(Observer) Javascript乱弹设计模式系列(0) 面向对象基础以及接口和继承类的实现 转载于:https://www.cnblogs.com/liping13599168/archive/2009/01/06/1366599.html