標籤:
Java實驗報告二:Java物件導向程式設計
20135231 何佳
實驗要求:
1. 初步掌握單元測試和TDD2. 理解並掌握物件導向三要素:封裝、繼承、多態3. 初步掌握UML建模4. 熟悉S.O.L.I.D原則5. 瞭解設計模式
實驗內容:
(一)單元測試(二)物件導向三要素(三)設計模式初步(四)練習
實驗步驟:
(一)單元測試
(1)
三種代碼
編程是智力活動,不是打字,編程前要把幹什麼、如何幹想清楚才能把程式寫對、寫好。與目前不少同學一說編程就開啟編輯器寫代碼不同,我希望同學們養成一個習慣,當你們想用程式解決問題時,要會寫三種碼:虛擬碼、產品代碼、測試代碼。
虛擬碼與具體程式設計語言無關,,虛擬碼從意圖層面來解決問題,最終,虛擬碼是產品代碼最自然的、最好的注釋。
代碼為:
public class MyUtil
{
public static String percentage2fivegrade(int grade)
{
//如果成績小於60,轉成“不及格”
if (grade < 60)
return "不及格";
//如果成績在60與70之間,轉成“及格”
else if (grade < 70)
return "及格";
//如果成績在70與80之間,轉成“中等”
else if (grade < 80)
return "中等";
//如果成績在80與90之間,轉成“良好”
else if (grade < 90)
return "良好";
//如果成績在90與100之間,轉成“優秀”
else if (grade < 100)
return "優秀";
//其他,轉成“錯誤”
else return "錯誤";
}
}
public class MyUtilTest
{
public static void main(String[] args)
{ //測試正常情況
if(MyUtil.percentage2fivegrade(55) != "不及格")
System.out.println("test failed!");
else if(MyUtil.percentage2fivegrade(65) != "及格")
System.out.println("test failed!");
else if(MyUtil.percentage2fivegrade(75) != "中等")
System.out.println("test failed!");
else if(MyUtil.percentage2fivegrade(85) != "良好")
System.out.println("test failed!");
else if(MyUtil.percentage2fivegrade(95) != "優秀")
System.out.println("test failed!");
else System.out.println("test passed!");
}
}
(2) TDD(Test Driven Devlopment,
測試驅動開發)
定義:先寫測試代碼,然後再寫產品代碼的開發方法
TDD一般步驟如下:
- 明確當前要完成的功能,記錄成一個測試清單
- 快速完成編寫針對此功能的測試案例
- 測試代碼編譯不通過(沒產品代碼呢)
- 編寫產品代碼
- 測試通過
- 對代碼進行重構,並保證測試通過(重構下次實驗練習)
- 迴圈完成所有功能的開發。
(二)物件導向三要素
(1)抽象
抽象一詞的本意是指人在認識思維活動中對事物表象因素的捨棄和對本質因素的抽取。抽象是人類認識複雜事物和現象時經常使用的思維工具,抽象思維能力在程式設計中非常重要,"去粗取精、化繁為簡、由表及裡、異中求同"的抽象能力很大程度上決定了程式員的程式設計能力。抽象就是抽出事物的本質特徵而暫時不考慮他們的細節。對於複雜系統問題人們藉助分層次抽象的方法進行問題求解;在抽象的最高層,可以使用問題環境的語言,以概括的方式敘述問題的解。在抽象的較低層,則採用過程化的方式進行描述。在描述問題解時,使用面向問題和面向實現的術語。 程式設計中,抽象包括兩個方面,一是過程抽象,二是資料抽象。
(2)封裝、繼承與多態
物件導向(Object-Oriented)的三要素包括:封裝、繼承、多態。物件導向的思想涉及到軟體開發的各個方面,如物件導向分析(OOA)、物件導向設計(OOD)、物件導向編程實現(OOP)。OOA根據抽象關鍵的問題域來分解系統,關注是什麼(what)。OOD是一種提供符號設計系統的物件導向的實現過程,用非常接近問題域術語的方法把系統構造成“現實世界”的對象,關注怎麼做(how),通過模型來實現功能規格。OOP則在設計的基礎上用程式設計語言(如Java)編碼。貫穿OOA、OOD和OOP的主線正是抽象。
(三)設計模式初步
(1)S.O.L.I.D原則
物件導向三要素是“封裝、繼承、多態”,任何物件導向程式設計語言都會在文法上支援這三要素。如何藉助抽象思維用好三要素特別是多態還是非常困難的,S.O.L.I.D類設計原則是一個很好的指導:
- SRP(Single Responsibility Principle,單一職責原則)
- OCP(Open-Closed Principle,開放-封閉原則)
- LSP(Liskov Substitusion Principle,Liskov替換原則)
- ISP(Interface Segregation Principle,介面分離原則)
- DIP(Dependency Inversion Principle,依賴倒置原則)
OCP是OOD中最重要的一個原則,OCP的內容是:
- software entities (class, modules, function, etc.) should open for extension,but closed for modification.
- 軟體實體(類,模組,函數等)應該對擴充開放,對修改封閉。
對擴充開放(Open For Extension )要求軟體模組的行為必須是可以擴充的,在應用需求改變或需要滿足新的應用需求時,我們要讓模組以不同的方式工作; 對修改封閉(Closed for Modification )要求模組的原始碼是不可改動的,任何人都不許修改已有模組的原始碼。 基於OCP,利用物件導向中的多態性(Polymorphic),更靈活地處理變更擁抱變化,OCP可以用以下手段實現:(1)抽象和繼承,(2)面向介面編程。
SRP的內容是:
- There should never be more than one reason for a class to change
- 決不要有一個以上的理由修改一個類
對象提供單一職責的高度封裝,對象的改變僅僅依賴於單一職責的改變,它基於軟體設計中的高內聚性定義。
LSP的內容是:
- Subtypes must be substitutable for their base types
- Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it
- 子類必須可以被其基類所代
- 使用指向基類的指標或引用的函數,必須能夠在不知道具體衍生類別物件類型的情況下使用它
ISP的內容是:
- Clients should not be forced to depend upon interfaces that they do not use
- 客戶不應該依賴他們並未使用的介面
DIP的內容是:
- High level modules should not depend upon low level modules. Both should depend upon abstractions
- Abstractions should not depend upon details. Details should depend upon abstractions
- 高層模組不應該依賴於低層模組。二者都應該依賴於抽象
- 抽象不應該依賴於細節。細節應該依賴於抽象
(2)模式與設計模式
模式是某外在環境(Context) 下﹐對特定問題(Problem)的慣用解決之道(Solution)。模式必須使得問題明晰,闡明為什麼用它來求解問題,以及在什麼情況下有用,什麼情況下不能起作用,每個模式因其重複性從而可被複用,本身有自己的名字,有可傳授性,能移植到不同情景下。模式可以看作對一個問題可複用的專家級解決方案。 電腦科學中有很多模式:
- GRASP模式
- 分析模式
- 軟體體繫結構模式
- 設計模式:建立型,結構型,行為型
- 管理員模式: The Manager Pool 實現模式
- 介面設計互動模式
這裡面最重要的是設計模式,在物件導向中設計模式的地位可以和面向過程編程中的資料結構的地位相當。
(3)設計模式實樣本
設計模式(design pattern)提供一個用於細化軟體系統的子系統或組件,或它們之間的關係圖,它描述通訊組件的公用再現結構,通訊組件可以解決特定語境中的一個設計問題。 ,隨著系統中對象的數量增多,對象之間的互動成指數增長,設計模式可以幫我們以最好的方式來設計系統。設計模式背後是抽象和SOLID原則。 設計模式有四個基本要素:
- Pattern name:描述模式,便於交流,存檔
- Problem:描述何處應用該模式
- Solution:描述一個設計的組成元素,不針對特例
- Consequence:應用該模式的結果和權衡(trade-offs)
Java類庫中大量使用設計模式:
- Factory:java.util.Calendar
- Compsite:java.awt.Container
- Decorator:java I/0
- Iterator:java.util.Enumeration
- Strategy:java.awt.LayoutManager
(四)練習
1.使用TDD的方式設計關實現複數類Complex。
虛擬碼
- 無輸入 --- 則複數的實部為0,虛部為0
- 僅輸入實部 --- 複數的實部為所輸入的實部,虛部為0
- 僅輸入虛部 --- 複數的實部為0,虛部為所輸入的虛部
- 實部虛部都輸入 --- 複數的實部與虛部對應相應輸入的實部虛部。
- 加法 --- 複數的實部與實部相加,虛部與虛部相加 ,即輸出p1.rePart+p2.rePart,p1.imPart+p2.imPart
- 減法 --- 複數的實部與實部相減,虛部與虛部相減 , 即輸出 p1.rePart-p2.rePart,p1.imPart-p2.imPart
測試代碼
public class ComplexTest
{
public static void main(String[] args)
{
Complex c=new Complex();
Complex c1=new Complex(4,8);
Complex c2=new Complex(2,5);
c1.Print();
c2.Print();
System.out.println("兩複數的和為:");
System.out.println((c.Jia(c1, c2).rePart+"+"+c.Jia(c1, c2).imPart+"i").toString());
System.out.println("兩複數的差為:");
System.out.println(c.Jian(c1, c2).rePart+"+"+c.Jian(c1, c2).imPart+"i");
}
}
產品代碼
public class ComplexTest
{
public static void main(String[] args)
{
Complex c=new Complex();
Complex c1=new Complex(4,8);
Complex c2=new Complex(2,5);
c1.Print();
c2.Print();
System.out.println("兩複數的和為:");
System.out.println((c.Jia(c1, c2).rePart+"+"+c.Jia(c1, c2).imPart+"i").toString());
System.out.println("兩複數的差為:");
System.out.println(c.Jian(c1, c2).rePart+"+"+c.Jian(c1, c2).imPart+"i");
}
}
2.實驗報告中統計自己的PSP(Personal Software Process)時間
步驟 |
耗時 |
百分比 |
需求分析 |
40min |
16% |
設計 |
60min |
24% |
代碼實現 |
90min |
36% |
測試 |
30min |
12% |
分析總結 |
30min |
12% |
總結單元測試的好處:
先寫測試代碼,可以引導我去完成一個可以實現這些功能的類,對所編代碼有一個整體的把握。並且能讓自己負責的模組功能定義盡量明確,模組內部的改變不會影響其他模組,而且模組的品質能得到穩定的、量化的保證。
java第二次實驗報告20135231