一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看

java語(yǔ)言

Java代碼復用規則

時(shí)間:2025-02-14 09:23:41 java語(yǔ)言 我要投稿

Java代碼復用規則

  引導語(yǔ):代碼復用就是利用已有的代碼,或者相關(guān)的知識去編寫(xiě)新的代碼來(lái)構造軟件。以下是百分網(wǎng)小編分享給大家的Java代碼復用規則,歡迎閱讀!

  代碼復用的規則

  代碼復用是絕大多數程序員所期望的,也是OO的目標之一?偨Y我多年的編碼經(jīng)驗,為了使代碼能夠最大程度上復用,應該特別注意以下幾個(gè)方面。

  對接口編程

  "對接口編程"是面向對象設計(OOD)的第一個(gè)基本原則。它的含義是:使用接口和同類(lèi)型的組件通訊,即,對于所有完成相同功能的組件,應該抽象出一個(gè)接口,它們都實(shí)現該接口。具體到JAVA中,可以是接口(interface),或者是抽象類(lèi)(abstract class),所有完成相同功能的組件都實(shí)現該接口,或者從該抽象類(lèi)繼承。我們的客戶(hù)代碼只應該和該接口通訊,這樣,當我們需要用其它組件完成任務(wù)時(shí),只需要替換該接口的實(shí)現,而我們代碼的其它部分不需要改變!

  當現有的組件不能滿(mǎn)足要求時(shí),我們可以創(chuàng )建新的組件,實(shí)現該接口,或者,直接對現有的組件進(jìn)行擴展,由子類(lèi)去完成擴展的功能。

  優(yōu)先使用對象組合,而不是類(lèi)繼承

  "優(yōu)先使用對象組合,而不是類(lèi)繼承"是面向對象設計的第二個(gè)原則。并不是說(shuō)繼承不重要,而是因為每個(gè)學(xué)習OOP的人都知道OO的基本特性之一就是繼承,以至于繼承已經(jīng)被濫用了,而對象組合技術(shù)往往被忽視了。下面分析繼承和組合的優(yōu)缺點(diǎn):

  類(lèi)繼承允許你根據其他類(lèi)的實(shí)現來(lái)定義一個(gè)類(lèi)的實(shí)現。這種通過(guò)生成子類(lèi)的復用通常被稱(chēng)為白箱復用(white-box reuse)。術(shù)語(yǔ)"白箱"是相對可視性而言:在繼承方式中,父類(lèi)的內部細節對子類(lèi)可見(jiàn)。

  對象組合是類(lèi)繼承之外的另一種復用選擇。新的更復雜的功能可以通過(guò)組合對象來(lái)獲得。對象組合要求對象具有良好定義的接口。這種復用風(fēng)格被稱(chēng)為黑箱復用(black-box reuse),因為被組合的對象的內部細節是不可見(jiàn)的。對象只以"黑箱"的形式出現。

  繼承和組合各有優(yōu)缺點(diǎn)。類(lèi)繼承是在編譯時(shí)刻靜態(tài)定義的,且可直接使用,類(lèi)繼承可以較方便地改變父類(lèi)的實(shí)現。但是類(lèi)繼承也有一些不足之處。首先,因為繼承在編譯時(shí)刻就定義了,所以無(wú)法在運行時(shí)刻改變從父類(lèi)繼承的實(shí)現。更糟的是,父類(lèi)通常至少定義了子類(lèi)的部分行為,父類(lèi)的任何改變都可能影響子類(lèi)的行為。如果繼承下來(lái)的實(shí)現不適合解決新的問(wèn)題,則父類(lèi)必須重寫(xiě)或被其他更適合的類(lèi)替換。這種依賴(lài)關(guān)系限制了靈活性并最終限制了復用性。

  對象組合是通過(guò)獲得對其他對象的引用而在運行時(shí)刻動(dòng)態(tài)定義的。由于組合要求對象具有良好定義的接口,而且,對象只能通過(guò)接口訪(fǎng)問(wèn),所以我們并不破壞封裝性;只要類(lèi)型一致,運行時(shí)刻還可以用一個(gè)對象來(lái)替代另一個(gè)對象;更進(jìn)一步,因為對象的實(shí)現是基于接口寫(xiě)的,所以實(shí)現上存在較少的依賴(lài)關(guān)系。

  優(yōu)先使用對象組合有助于你保持每個(gè)類(lèi)被封裝,并且只集中完成單個(gè)任務(wù)。這樣類(lèi)和類(lèi)繼承層次會(huì )保持較小規模,并且不太可能增長(cháng)為不可控制的龐然大物(這正是濫用繼承的后果)。另一方面,基于對象組合的設計會(huì )有更多的對象(但只有較少的類(lèi)),且系統的行為將依賴(lài)于對象間的關(guān)系而不是被定義在某個(gè)類(lèi)中。

  注意:理想情況下,我們不用為獲得復用而去創(chuàng )建新的組件,只需要使用對象組合技術(shù),通過(guò)組裝已有的組件就能獲得需要的功能。但是事實(shí)很少如此,因為可用的組件集合并不豐富。使用繼承的復用使得創(chuàng )建新的組件要比組裝已有的組件來(lái)得容易。這樣,繼承和對象組合常一起使用。然而,正如前面所說(shuō),千萬(wàn)不要濫用繼承而忽視了對象組合技術(shù)。

  相關(guān)的設計模式有: Bridge、Composite、Decorator、Observer、Strategy等。

  下面的例子演示了這個(gè)規則,它的前提是:我們對同一個(gè)數據結構,需要以任意的格式輸出。

  第一個(gè)例子,我們使用基于繼承的框架,可以看到,它很難維護和擴展。

  abstract class AbstractExampleDocument

  {

  // skip some code ...

  public void output(Example structure)

  {

  if( null != structure )

  {

  this.format( structure );

  }

  }

  protected void format(Example structure);

  }

  第二個(gè)例子,我們使用基于對象組合技術(shù)的框架,每個(gè)對象的任務(wù)都清楚的分離開(kāi)來(lái),我們可以替換、擴展格式類(lèi),而不用考慮其它的任何事情。

  class DefaultExampleDocument

  {

  // skip some code ...

  public void output(Example structure)

  {

  ExampleFormatter formatter =

  (ExampleFormatter) manager.lookup(Roles.FORMATTER);

  if( null != structure )

  {

  formatter.format(structure);

  }

  }

  }

  這里,用到了類(lèi)似于"抽象工廠(chǎng)"的組件創(chuàng )建模式,它將組件的創(chuàng )建過(guò)程交給manager來(lái)完成;ExampleFormatter是所有格式的抽象父類(lèi);

  將可變的部分和不可變的部分分離

  "將可變的部分和不可變的部分分離"是面向對象設計的第三個(gè)原則。如果使用繼承的復用技術(shù),我們可以在抽象基類(lèi)中定義好不可變的部分,而由其子類(lèi)去具體實(shí)現可變的部分,不可變的部分不需要重復定義,而且便于維護。如果使用對象組合的復用技術(shù),我們可以定義好不可變的部分,而可變的部分可以由不同的組件實(shí)現,根據需要,在運行時(shí)動(dòng)態(tài)配置。這樣,我們就有更多的時(shí)間關(guān)注可變的部分。

  對于對象組合技術(shù)而言,每個(gè)組件只完成相對較小的功能,相互之間耦合比較松散,復用率較高,通過(guò)組合,就能獲得新的功能。

  減少方法的長(cháng)度

  通常,我們的方法應該只有盡量少的幾行,太長(cháng)的方法會(huì )難以理解,而且,如果方法太長(cháng),則應該重新設計。對此,可以總結為以下原則:

  ☆ 三十秒原則:如果另一個(gè)程序員無(wú)法在三十秒之內了解你的函數做了什么(What),如何做(How)以及為什么要這樣做(Why),那就說(shuō)明你的代碼是難以維護的,必須得到提高;

  ☆ 一屏原則:如果一個(gè)函數的代碼長(cháng)度超過(guò)一個(gè)屏幕,那么或許這個(gè)函數太長(cháng)了,應該拆分成更小的子函數;

  ☆ 一行代碼盡量簡(jiǎn)短,并且保證一行代碼只做一件事:那種看似技巧性的冗長(cháng)代碼只會(huì )增加代碼維護的難度。

  消除case / if語(yǔ)句

  要盡量避免在代碼中出現判斷語(yǔ)句,來(lái)測試一個(gè)對象是否某個(gè)特定類(lèi)的實(shí)例。通常,如果你需要這么做,那么,重新設計可能會(huì )有所幫助。我在工作中遇到這樣的一個(gè)問(wèn)題:我們在使用JAVA做XML解析時(shí),對每個(gè)標簽映射了一個(gè)JAVA類(lèi),采用SAX(簡(jiǎn)單的XML接口A(yíng)PI:Simple API for XML)模型。結果,代碼中反復出現了大量的判斷語(yǔ)句,來(lái)測試當前的標簽類(lèi)型。為此,我們重新設計了DTD(文檔類(lèi)型定義:Document Type Definition),為每個(gè)標簽增加了一個(gè)固定的屬性:classname,而且重新設計了每個(gè)標簽映射的JAVA類(lèi)的接口,統一了每個(gè)對象的操作:

  addElement(Element aElement); //增加子元素

  addAttribute(String attName, String attValue); //增加屬性;

  則徹底消除了所有的測試當前的標簽類(lèi)型的判斷語(yǔ)句。每個(gè)對象通過(guò) Class.forName(aElement.attributes.getAttribute("classname")).newInstence(); 動(dòng)態(tài)創(chuàng )建,

  減少參數個(gè)數

  有大量參數需要傳遞的方法,通常很難閱讀。我們可以將所有參數封裝到一個(gè)對象中來(lái)完成對象的傳遞,這也有利于錯誤跟蹤。

  許多程序員因為,太多層的對象包裝對系統效率有影響。是的,但是,和它帶來(lái)的好處相比,我們寧愿做包裝。畢竟,"封裝"也是OO的基本特性之一,而且,"每個(gè)對象完成盡量少(而且簡(jiǎn)單)的功能",也是OO的一個(gè)基本原則。

  類(lèi)層次的最高層應該是抽象類(lèi)

  在許多情況下,提供一個(gè)抽象基類(lèi)有利做特性化擴展。由于在抽象基類(lèi)中,大部分的功能和行為已經(jīng)定義好,使我們更容易理解接口設計者的意圖是什么。

  由于JAVA不允許"多繼承",從一個(gè)抽象基類(lèi)繼承,就無(wú)法再從其它基類(lèi)繼承了。所以,提供一個(gè)抽象接口(interface)是個(gè)好主意,一個(gè)類(lèi)可以實(shí)現多個(gè)接口,從而模擬實(shí)現了"多繼承",為類(lèi)的設計提供了更大的靈活性。

  盡量減少對變量的直接訪(fǎng)問(wèn)

  對數據的封裝原則應該規范化,不要把一個(gè)類(lèi)的屬性暴露給其它類(lèi),而是應該通過(guò)訪(fǎng)問(wèn)方法去保護他們,這有利于避免產(chǎn)生波紋效應。如果某個(gè)屬性的名字改變,你只需要修改它的訪(fǎng)問(wèn)方法,而不是修改所有相關(guān)的代碼。

  子類(lèi)應該特性化,完成特殊功能

  如果一個(gè)子類(lèi)只是使一個(gè)組件變成組件管理器,而不是實(shí)現接口功能,或者,重載某個(gè)功能,那么,就應該使用一個(gè)外部的容器類(lèi),而不是創(chuàng )建一個(gè)子類(lèi)。

  建議:類(lèi)層次結構圖,不要太深;

  例如:下面的接口定義了組件的功能:發(fā)送消息;類(lèi)Transceiver實(shí)現了該接口;而其子類(lèi)Pool只是管理多個(gè)Transceiver對象,而沒(méi)有提供自己的接口實(shí)現。建議使用組合方式,而不是繼承!

  public interface ITransceiver{

  public abstract send(String msg);

  }

  public class Transceiver implements ITransceiver {

  public send(String msg){

  System.out.println(msg);

  }

  }

  //使用繼承方式的實(shí)現

  public class Pool extends Transceiver{

  private List pool = new Vector();

  public void add(Transceiver aTransceiver){

  pool.add(aTransceiver);

  }

  public Transceiver get(int index){

  pool.get(index);

  }

  }

  //使用組合方式的實(shí)現

  public class Pool {

  private List pool = new Vector();

  public void add(Transceiver aTransceiver){

  pool.add(aTransceiver);

  }

  public Transceiver get(int index){

  pool.get(index);

  }

  }

  拆分過(guò)大的類(lèi)

  如果一個(gè)類(lèi)有太多的方法(超過(guò)50個(gè)),那么它可能要做的工作太多,我們應該試著(zhù)將它的功能拆分到不同的類(lèi)中,類(lèi)似于規則四。

  作用截然不同的對象應該拆分

  在構建的過(guò)程中,你有時(shí)會(huì )遇到這樣的問(wèn)題:對同樣的數據,有不同的視圖。某些屬性描述的是數據結構怎樣生成,而某些屬性描述的是數據結構本身。最好將這兩個(gè)視圖拆分到不同的類(lèi)中,從類(lèi)名上就可以區分出不同視圖的作用。

  類(lèi)的域、方法也應該有同樣的考慮!

  盡量減少對參數的隱含傳遞

  兩個(gè)方法處理類(lèi)內部同一個(gè)數據(域),并不意味著(zhù)它們就是對該數據(域)做處理。許多時(shí)候,該數據(域)應該作為方法的參輸入數,而不是直接存取,在工具類(lèi)的設計中尤其應該注意。例如:

  public class Test{

  private List pool = new Vector();

  public void testAdd(String str){

  pool.add(str);

  }

  public Object testGet(int index){

  pool.get(index);

  }

  }

  兩個(gè)方法都對List對象pool做了操作,但是,實(shí)際上,我們可能只是想對List接口的不同實(shí)現Vector、ArrayList等做存取測試。所以,代碼應該這樣寫(xiě):

  public class Test{

  private List pool = new Vector();

  public void testAdd(List pool, String str){

  pool.add(str);

  }

  public Object testGet(List pool, int index){

  pool.get(index);

【Java代碼復用規則】相關(guān)文章:

java語(yǔ)言代碼復用規則04-23

java常用代碼07-07

Java for循環(huán)的寫(xiě)法代碼08-01

java代碼的基本要點(diǎn)08-01

JAVA代碼的基本格式07-22

Java代碼格式規范05-08

JAVA代碼優(yōu)化總結05-18

Java代碼的基本知識04-16

java常見(jiàn)的排序算法的代碼03-26

一级日韩免费大片,亚洲一区二区三区高清,性欧美乱妇高清come,久久婷婷国产麻豆91天堂,亚洲av无码a片在线观看