重构(Refactoring)就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。--百度百科
什么时候开始重构?为什么要重构?怎么衡量重构的好坏?
答案可以直接参考:http://baike.baidu.com/view/120901.htm 百度百科
个人觉得重构就是改善,使自己认识到重构的好处,前面二次的代码。
javascript-焦点图实现(一)
javascript-焦点图实现(二)
重构的价值在哪里?
直接用到上面的效果,上面的代码也不复杂,不用浪费时间去重构。
简单的实现对结构的要求不是很高,如果基于上面代码进行扩展时,代码不断增多,结构就很重要。
实践:
下面一段代码
Slider效果
对原来的html结构也有所改变。
<style> #focus_view td{ height:200px; color:#fff; } </style> <div id="focus_view"> <table width="500" border="0" cellspacing="0" cellpadding="0"> <tr> <td style="background:#f00;">1</td> <td style="background:#ff0;">2</td> <td style="background:#f0f;">3</td> <td style="background:#0f0;">4</td> <td style="background:#000;">5</td> <td style="background:#00f;">6</td> </tr> </table> </div> <button id="focus_prev">上一项</button><button id="focus_next">下一项</button>
javascript代码:
1 <script> 2 3 function extend(subClass,superClass){//类式继承 来自于《javascript 设计模式》 4 var f=function(){}; 5 f.prototype=superClass.prototype; 6 subClass.prototype=new f; 7 subClass.prototype.constructor=subClass; 8 } 9 13 14 /* 15 导入 Focus类 *必需 16 继承自Focus类, 17 添加方法 18 play,//播放 19 stop,//停止 20 setSpeed,//间隔 21 setEffect//效果 22 重写方法: 23 goto 24 init 25 26 */ 27 function FocusSlider(options){ 28 this._focusItems=options.focusItems; 29 this.autoPlay=options.autoPlay||true; 30 this._speed=options.speed||3000; 31 this._root=options.root; 32 this.width=500; 33 this.height=200; 34 this._interval=null; 35 this._isMoved=false;//添加一个动画播放时的锁定 36 Focus.call(this,this._focusItems,options.callBackFn,options.effectFn); 37 this.init(); 38 this.play(); 39 } 40 extend(FocusSlider,Focus); 41 42 FocusSlider.prototype.init=function(){ 43 for(var i=0,len=this.size();i<len;i++){ 44 this._focusItems[i].style.position="absolute"; 45 this._focusItems[i].style.left=1000+"px"; 46 this._focusItems[i].style.width=this.width+"px"; 47 this._focusItems[i].style.height=this.height+"px"; 48 } 49 this._root.style.position="relative"; 50 this._root.style.overflow="hidden"; 51 this._root.style.display="block"; 52 this._root.style.width=this.width+"px"; 53 this._root.style.height=this.height+"px"; 54 55 this._focusItems[0].style.left="0"; 56 } 57 FocusSlider.prototype.setEffect=function(fun){ 58 this._effectFn=fun; 59 } 60 61 FocusSlider.prototype.setSpeed=function(speed){ 62 this._speed=speed; 63 } 64 65 FocusSlider.prototype.play=function(){ 66 var that=this; 67 that._interval=setInterval(function(){that.next();},that._speed) 68 } 69 FocusSlider.prototype.stop=function(){ 70 this._interval&&clearInterval(this._interval) 71 } 72 FocusSlider.prototype.goto=function(num){ 73 if(this._isMoved)return; 74 this.setIndex(num); 75 this._effectFn&&this._effectFn.call(this,this._currentIndex,this._focusItems); 76 77 } 83 84 var getItselfNot=(function(){//取自身反,用单例模式来实现 85 var states=1; 86 return function(){ 87 return states=!states; 88 } 89 })() 90 91 function playSlider(index,arr){ 92 for(var i=0,len=arr.length;i<len;i++){ 93 arr[i].style.zIndex="0"; 94 arr[i].style.display="none"; 95 } 96 arr[(index==0?arr.length:index)-1].style.display=""; 97 arr[index].style.zIndex="5"; 98 arr[index].style.display=""; 99 arr[index].style.left=this.width+"px"; 100 this._isMoved=true; 101 var that=this; 102 var start=new Date(); 103 var time=800; 104 var orignalVal=(getItselfNot()?-1:1)*this.width; 105 var targetVal=0; 106 var diffVal=targetVal-orignalVal; 107 (function step(){ 108 var past=(new Date())-start; 109 var rate=past/time; 110 arr[index].style.left=orignalVal+rate*diffVal+"px"; 111 if(rate<1){ 112 setTimeout(function(){ step();},Math.min(20,time-past)); 113 }else{ 114 arr[index].style.left=targetVal+"px"; 115 that._isMoved=false; 116 } 117 })() 118 } 119 120 121 122 123 //以下为测试代码 124 125 var prev=document.getElementById("focus_prev"); 126 var next=document.getElementById("focus_next"); 127 128 var focusView=document.getElementById("focus_view"); 129 var focusItems=focusView.getElementsByTagName("td"); 130 131 //声明 132 var fos=new FocusSlider({'focusItems':focusItems,"root":focusView}); 133 //设置切换效果 134 fos.setEffect(playSlider); 135 136 //后一项 137 next.onclick=function(){ 138 fos.next(); 139 } 140 //前一项 141 prev.onclick=function(){ 142 fos.prev(); 143 } 144 145 //停止 146 focusView.onmouseover=function(){ 147 fos.stop(); 148 } 149 //播放 150 focusView.onmouseout=function(){ 151 fos.play(); 152 } 153 154 155 </script>
效果:
分析:
能过写上面的代码,发现和焦点(二)的代码里有的方法是重复的,
变化的部分是effectFn,init,方法。
重构思路:
对变化部分的处理,effectFn,init等方法单独处理。
对不变部分play,stop,prev,next,goto等方法提取。
把Effect提取出来成为一个效果集合,
通过getEffect:获取对应效果对象
通过setEffect:添加新的效果对象。参数包括效果名,效果对象
Effect对象里包括方法init,exec