課程:Java程序設計 班級:1652班 姓名:王高源 學號:20165225 指導教師:婁嘉鵬 實驗日期:2018年4月16日 實驗時間:3:35 - 5:15 實驗序號:實驗二 實驗名稱:Java面向對象程序設計 實驗內容: 1.初步掌握單元測試和TDD 2.理解並掌握面向對象三要素:封裝、繼承、多態 3.初步掌握UML建模 4.熟悉S.O.L.I.D原則 5.瞭解設計模式 實驗要求: 實現百分制成績轉成「優、良、中、及格、不及格」五級製成績的功能
TDD步驟:僞代碼(思路)→ 測試代碼(產品預期功能)→ 產品代碼(實現預期功能),這種開發方法叫「測試驅動開發」html
僞代碼:僞代碼與具體編程語言無關,不要寫與具體編程語言語法相關的語句(如用malloc分配內存,這樣只能用C語言編程了),僞代碼從意圖層面來解決問題,最終,僞代碼是產品代碼最天然的、最好的註釋。java
百分制轉五分制: 若是成績小於60,轉成「不及格」 若是成績在60與70之間,轉成「及格」 若是成績在70與80之間,轉成「中等」 若是成績在80與90之間,轉成「良好」 若是成績在90與100之間,轉成「優秀」 其餘,轉成「錯誤」
可見使用語言簡潔明瞭,隨後將僞代碼轉爲產品代碼便可。git
public class MyUtil{ public static String percentage2fivegrade(int grade){ //若是成績小於0,轉成「錯誤」 if ((grade < 0)) return "錯誤"; //若是成績小於60,轉成「不及格」 else 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 "優秀"; //若是成績大於100,轉成「錯誤」 else return "錯誤"; } }
寫了產品代碼後,咱們還要寫測試代碼,證實本身的代碼沒有問題,這樣才能將代碼放心交到用戶手中。編程
public class MyUtilTest { public static void main(String[] args) { // 百分制成績是50時應該返回五級制的「不及格」 if(MyUtil.percentage2fivegrade(50) != "不及格") System.out.println("test failed!"); else System.out.println("test passed!"); } }
成功了。設計模式
不過只測一組就是有偷懶嫌疑了,如今咱們把通常狀況都試一下:網絡
也成功了app
再看看異常狀況下的測試:編程語言
public class MyUtil{ public static String percentage2fivegrade(int grade){ //若是成績小於0,轉成「錯誤」 if ((grade < 0)) return "錯誤"; //若是成績小於60,轉成「不及格」 else 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 "優秀"; //若是成績大於100,轉成「錯誤」 else return "錯誤"; } }
public class MyUtilTest { public static void main(String[] args) { //測試邊界狀況 if(MyUtil.percentage2fivegrade(0) != "不及格") System.out.println("test failed 1!"); else if(MyUtil.percentage2fivegrade(60) != "及格") System.out.println("test failed 2!"); else if(MyUtil.percentage2fivegrade(70) != "中等") System.out.println("test failed 3!"); else if(MyUtil.percentage2fivegrade(80) != "良好") System.out.println("test failed 4!"); else if(MyUtil.percentage2fivegrade(90) != "優秀") System.out.println("test failed 5!"); else if(MyUtil.percentage2fivegrade(100) != "優秀") System.out.println("test failed 6!"); else System.out.println("test passed!"); } }
public class MyUtil{ public static String percentage2fivegrade(int grade){ //若是成績小於0,轉成「錯誤」 if ((grade < 0)) return "錯誤"; //若是成績小於60,轉成「不及格」 else 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 "優秀"; //若是成績大於100,轉成「錯誤」 else return "錯誤"; } }
成功了。ide
值得一提的是,Java中有單元測試工具JUnit來輔助進行TDD。模塊化
按照老師給的步驟來走不當心就出現下圖,覺得是網絡問題,結果換了網也沒有用:
氣死了,再下一次,發現他又好了...
回到原題。
從網上下了一個everything用於查找junit.jar。
而後用老師給的新方法去測試了一下以前的代碼:
成功了,而後多是版本問題,個人小綠條變成了小綠勾。
其實以前按照攻略來是失敗了的,不過還好有好看的助教學姐指點了我一下,才順利完成測試。
面向對象(Object-Oriented)的三要素包括:封裝、繼承、多態。面向對象的思想涉及到軟件開發的各個方面,如面向對象分析(OOA)、面向對象設計(OOD)、面向對象編程實現(OOP)。OOA根據抽象關鍵的問題域來分解系統,關注是什麼(what)。OOD是一種提供符號設計系統的面向對象的實現過程,用很是接近問題域術語的方法把系統構形成「現實世界」的對象,關注怎麼作(how),經過模型來實現功能規範。OOP則在設計的基礎上用編程語言(如Java)編碼。貫穿OOA、OOD和OOP的主線正是抽象。
抽象:即「求同存異、去粗取精」的過程。將若干事物中相同的部分進行剝離整理,並造成具備某特定功能的產品,這一過程即爲抽象。過程抽象的結果是函數,數據抽象的結果是抽象數據類型其顯而易見的好處是(在程序設計中)減小了代碼大重複性,提升了效率。
封裝:將與某一將數據與相關行爲包裝在一塊兒以實現信息就隱藏,核心內容是模塊化和信息隱藏,與此相伴的是接口的使用。
public class Dog { private String color; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String bark(){ return "汪汪"; } public String toString(){ return "The Dog's color is " + this.getColor() +", and it shouts "+ this.bark() + "!"; } }
public class DogTest { public static void main(String[] args) { Dog d = new Dog(); d.setColor("Yellow"); getInfo(d); } public static void getInfo(Dog d) { System.out.println(d.toString()); } }
public class StringBufferDemo { public static void main(String [] args) { StringBuffer buffer = new StringBuffer(); buffer.append('S'); buffer.append("tringBuffer"); System.out.println(buffer.charAt(i)); System.out.println(buffer.capacity()); System.out.println(buffer.length()); System.out.println(buffer.indexOf("tring")); System.out.println("buffer = " + buffer.toString()); } }
然而老師說這個代碼不能夠直接用,在我把第七行的括號加上後,便完美運行了。
在老師給出的使用JUnit學習Java中,有四個須要咱們去測試的東西:charAt()、capacity()、length()和indexOf。
import junit.framework.TestCase; import org.junit.Test; public class StringBufferDemoTest extends TestCase { StringBuffer a = new StringBuffer("StringBuffer"); StringBuffer b = new StringBuffer("StringBufferStringBuffer"); StringBuffer c = new StringBuffer("StringBufferStringBufferStringBuffer"); @Test public void testcharAt() { assertEquals('S',a.charAt(0)); assertEquals('e',b.charAt(10)); assertEquals('f',c.charAt(20));; } @Test public void testcapacity() { assertEquals(28,a.capacity()); assertEquals(40,b.capacity()); assertEquals(52,c.capacity()); } @Test public void testindexOf() { assertEquals(0,a.indexOf("Str")); assertEquals(3,b.indexOf("ing")); assertEquals(10,c.indexOf("er")); } @Test public void testlength() { assertEquals(12,a.length()); assertEquals(24,b.length()); assertEquals(48,c.length()); } }
SRP(Single Responsibility Principle,單一職責原則)
對象提供單一職責的高度封裝,對象的改變僅僅依賴於單一職責的改變
OCP(Open-Closed Principle,開放-封閉原則)
即對擴充開放(功能可增長),對修改封閉(源代碼不可改動)
OCP實現手段:(1)抽象和繼承,(2)面向接口編程
LSP(Liskov Substitusion Principle,Liskov替換原則)
子類必須能夠被其基類所代,父類型對象能夠被子類型對象所取代
ISP(Interface Segregation Principle,接口分離原則)
客戶不該該依賴他們並未使用的接口
DIP(Dependency Inversion Principle,依賴倒置原則)
示例以下(本身學號%6取餘):
abstract class Data { abstract public void DisplayValue(); } class Integer extends Data { int value; Integer() { value=100; } public void DisplayValue(){ System.out.println (value); } } class Short extends Data { short value; Short() { value = 5225; } public void DisplayValue(){ System.out.println (value); } } abstract class Factory { abstract public Data CreateDataObject(); } class IntFactory extends Factory { public Data CreateDataObject(){ return new Integer(); } } class ShortFactory extends Factory { public Data CreateDataObject(){ return new Short(); } } class Document { Data pd; Document(Factory pf){ pd = pf.CreateDataObject(); } public void DisplayData(){ pd.DisplayValue(); } } public class MyDoc { static Document d; public static void main(String[] args) { d = new Document(new ShortFactory()); d.DisplayData(); } }
class ??? extends Data { short value; Short() { value = 5225; } public void DisplayValue(){ System.out.println (value); } } class ???Factory extends Factory { public Data CreateDataObject(){ return new ???(); } } public class MyDoc { static Document d; public static void main(String[] args) { d = new Document(new ???Factory()); d.DisplayData(); } }
Complex類要輸出實部,輸出虛部,並按照a+bi的形式輸出複數。 Complex類中有兩個變量,實部RealPart和虛部ImaginePart;, double RealPart;複數的實部 double ImagePart;複數的虛部 getRealPart():返回複數的實部 getImagePart();返回複數的虛部 setRealPart():設置複數的實部 setImagePart();設置複數的虛部 輸出形式:a+bi (2)方法: // 定義構造函數 public Complex() public Complex(double R,double I) // 定義公有方法:加減乘除 Complex ComplexAdd(Complex a) 加 Complex ComplexSub(Complex a) 減 Complex ComplexMulti(Complex a) 乘 Complex ComplexDiv(Complex a) 除 //Override Object public boolean equals(Object obj) public String toString():將複數輸出成a+bi的格式。
import java.util.Scanner; public class MyComplex { static int r; static int i; private double m; private double n; public static int getRealPart(int RealPart){ r = RealPart; return r; } public static int getImaginePart(int ImaginePart){ i = ImaginePart; return i; } public MyComplex(double m, double n) { this.m = m; this.n = n; } public MyComplex add(MyComplex c) { return new MyComplex(m + c.m, n + c.n); } public MyComplex minus(MyComplex c) { return new MyComplex(m - c.m, n - c.n); } public MyComplex multiply(MyComplex c) { return new MyComplex(m * c.m - n * c.n, m * c.n + n * c.m); } public String toString() { String s = ""; if (n > 0) s = "(" + m + "+" + n + "i" + ")"; if (n == 0) s = "(" + m + ")"; if (n < 0) s = "(" + m + n + "i" + ")"; return s; } }
import org.junit.Test; import static org.junit.Assert.*; public class MyComplexTest { MyComplex a=new MyComplex(1,2); MyComplex b=new MyComplex(1,-4); MyComplex c=new MyComplex(19,0); MyComplex d=new MyComplex(0,-3); MyComplex e=new MyComplex(0,0); @Test public void getRealPart() throws Exception { assertEquals(1, MyComplex.getRealPart(1)); assertEquals(-1, MyComplex.getRealPart(-1)); assertEquals(5, MyComplex.getRealPart(5)); assertEquals(22, MyComplex.getRealPart(22)); assertEquals(-100, MyComplex.getRealPart(-100)); assertEquals(0, MyComplex.getRealPart(0)); } @Test public void getImaginePart() throws Exception { assertEquals(1, MyComplex.getImaginePart(1)); assertEquals(-1, MyComplex.getImaginePart(-1)); assertEquals(5, MyComplex.getImaginePart(5)); assertEquals(22, MyComplex.getImaginePart(22)); assertEquals(-100, MyComplex.getImaginePart(-100)); assertEquals(0, MyComplex.getImaginePart(0)); } @Test public void add() throws Exception { assertEquals("(2.0-2.0i)", a.add(b).toString()); assertEquals("(20.0+2.0i)", a.add(c).toString()); assertEquals("(1.0-1.0i)", a.add(d).toString()); assertEquals("(1.0+2.0i)", a.add(e).toString()); } @Test public void minus() throws Exception { assertEquals("(0.0+6.0i)", a.minus(b).toString()); assertEquals("(-18.0+2.0i)", a.minus(c).toString()); assertEquals("(1.0+5.0i)", a.minus(d).toString()); assertEquals("(1.0+2.0i)", a.minus(e).toString()); } @Test public void multiply() throws Exception { assertEquals("(9.0-2.0i)", a.multiply(b).toString()); assertEquals("(19.0+38.0i)", a.multiply(c).toString()); assertEquals("(6.0-3.0i)", a.multiply(d).toString()); assertEquals("(0.0)", a.multiply(e).toString()); } }
說實話,此次實驗要我編程我是不會編的..可是還好老師給了模板,只須要改一下就行了。
在實驗有了代碼支撐後,比較累的地方就是要看好多好多長博客,還有以上提到的一些軟件的操做方法你都要學(雖然老師有給出UML的另外一個建模方法,可是我仍是用了別的)。
值得一提的是,此次學到的東西能讓我更輕鬆的去修正代碼bug,減小了以後修復所須要的大量精力。
可是無論怎麼說,過程仍是很累的,有時候都想把博客所有關掉,好好睡一下,好在最後我寫完了。
仍是要繼續加油呀!
碼雲連接(這也是我第一次規範書寫git傳代碼哦)