當前位置:才華齋>計算機>java語言>

java語言程式碼複用規則

java語言 閱讀(7.66K)

Java語言是一種適用於網路程式設計的語言,它的基本結構與C++極為相似,但卻簡單得多。下面是小編分享的java語言程式碼複用規則,一起來看一下吧。

java語言程式碼複用規則

  程式碼複用的規則

程式碼複用是絕大多數程式設計師所期望的,也是OO的目標之一。總結我多年的編碼經驗,為了使程式碼能夠最大程度上覆用,應該特別注意以下幾個方面。

  對介面程式設計

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

當現有的元件不能滿足要求時,我們可以建立新的元件,實現該介面,或者,直接對現有的元件進行擴充套件,由子類去完成擴充套件的功能。

  優先使用物件組合,而不是類繼承

"優先使用物件組合,而不是類繼承"是面向物件設計的第二個原則。並不是說繼承不重要,而是因為每個學習OOP的人都知道OO的基本特性之一就是繼承,以至於繼承已經被濫用了,而物件組合技術往往被忽視了。下面分析繼承和組合的優缺點:

類繼承允許你根據其他類的實現來定義一個類的實現。這種通過生成子類的複用通常被稱為白箱複用(white-box reuse)。術語"白箱"是相對可視性而言:在繼承方式中,父類的內部細節對子類可見。

物件組合是類繼承之外的另一種複用選擇。新的更復雜的功能可以通過組合物件來獲得。物件組合要求物件具有良好定義的介面。這種複用風格被稱為黑箱複用(black-box reuse),因為被組合的物件的內部細節是不可見的。物件只以"黑箱"的形式出現。

繼承和組合各有優缺點。類繼承是在編譯時刻靜態定義的,且可直接使用,類繼承可以較方便地改變父類的實現。但是類繼承也有一些不足之處。首先,因為繼承在編譯時刻就定義了,所以無法在執行時刻改變從父類繼承的實現。更糟的是,父類通常至少定義了子類的部分行為,父類的任何改變都可能影響子類的行為。如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。這種依賴關係限制了靈活性並最終限制了複用性。

物件組合是通過獲得對其他物件的引用而在執行時刻動態定義的。由於組合要求物件具有良好定義的介面,而且,物件只能通過介面訪問,所以我們並不破壞封裝性;只要型別一致,執行時刻還可以用一個物件來替代另一個物件;更進一步,因為物件的實現是基於介面寫的,所以實現上存在較少的依賴關係。

優先使用物件組合有助於你保持每個類被封裝,並且只集中完成單個任務。這樣類和類繼承層次會保持較小規模,並且不太可能增長為不可控制的龐然大物(這正是濫用繼承的後果)。另一方面,基於物件組合的設計會有更多的物件(但只有較少的類),且系統的行為將依賴於物件間的'關係而不是被定義在某個類中。

注意:理想情況下,我們不用為獲得複用而去建立新的元件,只需要使用物件組合技術,通過組裝已有的元件就能獲得需要的功能。但是事實很少如此,因為可用的元件集合並不豐富。使用繼承的複用使得建立新的元件要比組裝已有的元件來得容易。這樣,繼承和物件組合常一起使用。然而,正如前面所說,千萬不要濫用繼承而忽視了物件組合技術。

相關的設計模式有: Bridge、Composite、Decorator、Observer、Strategy等。

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

第一個例子,我們使用基於繼承的框架,可以看到,它很難維護和擴充套件。

abstract class AbstractExampleDocument

{

// skip some code ...

public void output(Example structure)

{

if( null != structure )

{

at( structure );

}

}

protected void format(Example structure);

}

第二個例子,我們使用基於物件組合技術的框架,每個物件的任務都清楚的分離開來,我們可以替換、擴充套件格式類,而不用考慮其它的任何事情。

class DefaultExampleDocument

{

// skip some code ...

public void output(Example structure)

{

ExampleFormatter formatter =

(ExampleFormatter) up(ATTER);

if( null != structure )

{

at(structure);

}

}

}

這裡,用到了類似於"抽象工廠"的元件建立模式,它將元件的建立過程交給manager來完成;ExampleFormatter是所有格式的抽象父類;

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

"將可變的部分和不可變的部分分離"是面向物件設計的第三個原則。如果使用繼承的複用技術,我們可以在抽象基類中定義好不可變的部分,而由其子類去具體實現可變的部分,不可變的部分不需要重複定義,而且便於維護。如果使用物件組合的複用技術,我們可以定義好不可變的部分,而可變的部分可以由不同的元件實現,根據需要,在執行時動態配置。這樣,我們就有更多的時間關注可變的部分。

對於物件組合技術而言,每個元件只完成相對較小的功能,相互之間耦合比較鬆散,複用率較高,通過組合,就能獲得新的功能。

  減少方法的長度

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

三十秒原則:如果另一個程式設計師無法在三十秒之內瞭解你的函式做了什麼(What),如何做(How)以及為什麼要這樣做(Why),那就說明你的程式碼是難以維護的,必須得到提高;

一屏原則:如果一個函式的程式碼長度超過一個螢幕,那麼或許這個函式太長了,應該拆分成更小的子函式;

一行程式碼儘量簡短,並且保證一行程式碼只做一件事:那種看似技巧性的冗長程式碼只會增加程式碼維護的難度。

 消除case / if語句

要儘量避免在程式碼中出現判斷語句,來測試一個物件是否某個特定類的例項。通常,如果你需要這麼做,那麼,重新設計可能會有所幫助。我在工作中遇到這樣的一個問題:我們在使用JAVA做XML解析時,對每個標籤映射了一個JAVA類,採用SAX(簡單的XML介面API:Simple API for XML)模型。結果,程式碼中反覆出現了大量的判斷語句,來測試當前的標籤型別。為此,我們重新設計了DTD(文件型別定義:Document Type Definition),為每個標籤增加了一個固定的屬性:classname,而且重新設計了每個標籤對映的JAVA類的介面,統一了每個物件的操作:

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

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

則徹底消除了所有的測試當前的標籤型別的判斷語句。每個物件通過 ame(ttribute("classname"))nstence(); 動態建立,