Java资源网

| JAVA基础 | 环境配置 | JDBC | 线程技术 | Socket编程 | JavaMail | JAVA与XML | 设计模式 | 技术新闻 | Java认证 | 程序人生 软件下载
| JSP&Servlet | Spring | Struts | Hibernate | JBuilder | Eclipse | WebService | EJB技术 | J2ME开发 | 应用服务器 | JXTA | Ajax
Articles search文章搜索
   关键字:
   类 别:
       
New download 最新下载
· [组件]HTML Parser 1.5
· [教程]WebSphere Studio应用教程
· [组件]JDom 1.0
· [工具]Junit3.8.1
· [教程]EJB编程及J2EE系统架构和设计
· [教程]EJB教程
· [教程]J2EE Tutorial中文版
· [教程]Java编程思想2(英文)
· [教程]java编程思想(完整版)
· [教程]Java网络编程
New articles 最新文章
· 设计移动 Web 服务
· 解析XML的时候完全忽略DTD
· 理解XML Schema XML Schema 初步
· 标签库的深入研究
· 提升JSP应用程序的七大绝招
· 如何使用JDOM对XML文件进行操作
· 处理XML字符串中特殊字符
· 利用Digester把XML转换成为Java对象
· 使用WebService 和RMI远程协作
· 使用Axis开发Web Service程序
Articles top 热门文章
· Eclipse基础--plugin插件安装(6644)
· eclipse+tomcat+lomboz的安装配置说明(4774)
· Java程序员就业前景(4584)
· Windows下JAVA环境变量的设置祥解(3788)
· Tomcat下JSP、Servlet和JavaBean环境的配置(3716)
· 使用links方式安装Eclipse插件(3698)
· 一个老程序员的心理话(3533)
· linux下jdk的安装与配置(3459)
· 初学者入门:Structs中基本配置入门(3334)
· Eclipse 运行命令行参数大全(3084)
您的位置:首页>>JAVA基础>>设计迷踪:给JAVA设计开发新手的一些建议和意见(三)
设计迷踪:给JAVA设计开发新手的一些建议和意见(三)
2005-07-31   来源:CSDN  作者:scud(飞云小侠)

【空接口的使用】

 在接口使用的时候,空接口有2种情况:
 1.类似Cloneable,Serializable,他们往往是做一个标记,表示需要某个功能.当然你也可以这么用,来表示你的类具有某个功能,实现了你的某个接口.
 2.你的接口继承了别的接口(非空),你的接口本身没有声明函数.这种情况一般是你不希望用户使用父接口来作为参数类型,因为他们的用途可能不同,此时就可以用空接口来实现.
 
 第一种情况我们不再多说,搜索一下关于Cloneable,Serializable的文章就会了解很多.
 我们来看下面的代码:

  public interface Text
  {
   String getText();
  }
  
  public interface SqlText extends Text
  {
  }


 可以看到,Text接口是用于返回一个字符串.而SqlText是一个空接口,它继承了Text接口.也就是说SqlText也是一种Text.但是我们可以知道,任何一个字符串不一定是Sql字符串,所以此时声明了一个SqlText接口来用于表名当前的字符串是一个Sql字符串.你的函数可以这样声明: 


  public void doQuery(SqlText aSqlText)

而不是这样


  
  public void doQuery(Text aText)

避免用户产生歧义的想法,一眼看去,就明白应该传入一个Sql字符串.
 
  


【继承层次过多】
 一般来说,继承的层次不要过多,否则使用者可能会讨厌,找一个函数会很麻烦.很多Java语言检查工具都建议你的继承层次不要超过3层.
 
 
【Has A ,Is A,不要滥用继承】

 "我是一个Mp3","我有一个Mp3",其实很容易分辨.但是在实际应用中,往往存在把"我有一个Mp3"的情况当作"我是一个Mp3",或者是为了偷懒方便而放松了对自己的要求,甚至还沾沾自喜,感觉找到一个捷径.(scud以前也干过这种事情).
 
 以前我曾经这样干过:我的逻辑类直接继承了我的数据库访问类,这样我可以直接在逻辑类里面访问:
 

  public MyLogic extends MyDBA
  
  aLogic.getInt("click");
  aLogic.getString("name");
 

 看起来是非常方便,但是你的逻辑类就牢牢绑在了DBA上,是一种非常不好的做法.现在我这样声明:
  

  public MyLogic
   
   MyDBA adba;
   
   adba.getInt("click");
   adba.getString("name");
 

 其实代码改动不大,但是你的逻辑类不在牢牢绑在DBA身上了,何乐而不为.
 
 其实这种现象在开发人员中间可能经常见到,我们要尽量避免.下面再来看一个例子:
 
 //一个保存分页信息的类
 

 public class PageInfo
 {
  private int page;
  private int pageCount;
  private int recPerPage;
  private int recCount;  
  
  //get,set method list...
 }
 

 一般的情况是,在Dao中进行分页查询,计算总记录,总页数等等,所以需要把PageInfo传给Dao.而在逻辑类中,把传回来的分页信息数据推到FormBean或者是Action中.
 也许你会这么想,如果我的Action或者FormBean继承了PageInfo,岂不是要省很多事.
 
 千万别这么干.并不是所有的动作都需要分页信息,你的FormBean和PageInfo没有继承的关系.也就是说FormBean Has A PageInfo,但是不是Is A PageInfo.
 
 

【保持外观/行为一致】

 外观一致其实很容易理解,例如你用size()表示得到一个List的大小,那么在所有的List类中你都用size()得到它的大小,这就是外观一致.
 外观一致让用户更方便使用你的函数库,不用记住几个不同的表示同一个功能的函数名字.或者几个名字相同功能却不同的函数.那就很糟糕了.
 
 行为一致相对外观一致就相对比较难做到,但是优秀的设计师肯定会让他的成果行为一致,而不是出人意料的行为,也不是一套强行规定的行为.
 
 我们来看下面的代码:
 
 
   import java.util.HashMap;
   import java.util.Map;
   
   

 

   class UserInfo
   {
    private String realname;
    
    public UserInfo(String sName)
    {
     this.realname = sName;
    }
    
    public void setName(String sName)
    {
     this.realname = sName;
    }
    public String getName()
    {
     return this.realname;
    }  
   }
   
   
   public class MyTest
   {
      
    Map userInfoMap = new HashMap(); 
   
    public void setUserInfo(String sName,UserInfo aInfo)
    {
     userInfoMap.put(sName,aInfo);
     
        userInfoMap.put(aInfo.getName(),aInfo);
    }
    
    public UserInfo getUserInfo(String sName)
    {
     return (UserInfo)userInfoMap.get(sName);
    } 
    
    public static void main(String args[])
    {
     MyTest aTest = new MyTest();
     
     UserInfo aUserInfo = new UserInfo("王小二");
     
     aTest.setUserInfo("儿童团团长",aUserInfo);
     aTest.setUserInfo("三班班长",aUserInfo);
     
     UserInfo 儿童团团长 = aTest.getUserInfo("儿童团团长");
     
     if(null!=儿童团团长)
     {  
         System.out.println(儿童团团长.getName());
     }
     else
     {
         System.out.println("儿童团团长 Not Found");
     }
     
     UserInfo 王小二 = aTest.getUserInfo("王小二");
     
     if(null!=王小二)
     {  
         System.out.println(王小二.getName());
     }
     else
     {
         System.out.println("王小二 Not Found");
     }
     
    }
   }
     

 
 可以看到,上面的代码运行结果是"王小二",也就是说儿童团团长是王小二,王小二本身也是王小二,这一切正常.
 
 现在我们把setUserInfo里面的第一句注释掉:
 
 
    public void setUserInfo(String sName,UserInfo aInfo)
    {
     //userInfoMap.put(sName,aInfo);
     
        userInfoMap.put(aInfo.getName(),aInfo);
    }
    

 再次运行上面的代码,我们发现儿童团团长不存在了,但是王小二还在.还可以看出,如果找"三班班长"的话,肯定也找不到,也就是说只有依据王小二的真名才能找到王小二,其他方法就不行了.
 
 从上面的setUserInfo和getUserInfo分析,如果采用修改后的代码,我们的程序就出现了行为表现不一致,而这是令人迷惑不解的,我们set了半天,却找不到,岂不是令人恼火!
 
 当然上面的代码比较简单,通过简单的修改就能做到行为一致,但在实际编程中,往往因为复杂的行为操作,经常会造成行为不一致,从而给开发人员带来困惑.
 

 



作者Blog:http://blog.csdn.net/scud/
  --相关文章--
· J2EE全面介绍(二) (2007-04-13)
· 项目经验二则:读取war包中的文件及Ant使用中的OutOfMemoryError解决 (2007-04-13)
· 走向J2EE,漫长的道路 (2007-04-13)
· 步入J2EE架构和过程(2) (2007-04-13)
· 步入J2EE架构和过程(1) (2007-04-13)
· 方兴未艾的CORBA (2007-04-13)

版权所有©2005-2006 JAVA资源网 渝ICP备05007591号 虚拟主机 | 关于我们 | 联系方式 | 广告业务 | 网站地图 | 友情链接