日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OO第一次单元总结

發(fā)布時間:2023/12/2 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OO第一次单元总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第一次總結(jié)性博客

16071070 陳澤寅 2019.3.23

一、第一單元所學(xué)總結(jié)

  • 首先先來總結(jié)一下第一單元我所學(xué)到的知識以及所感所悟。第一個單元,是我第一次接觸JAVA語言,并且再使用了幾次之后,就被這門語言的獨有的魅力以及簡便的用法所深深吸引。下面我從三個方面來簡單闡述一下我對于JAVA相比較于c語言的優(yōu)勢。
    • (1)從架構(gòu)上來說,java的設(shè)計思路是不同于c的,它是一門面向?qū)ο蟮恼Z言,我們的思維從熟悉的過程式編程語言轉(zhuǎn)移到了對象思維上來。這樣的思維的好處是,我們可以將一個大的問題分成很多個小的類去進行處理。如果說過程式編程是一個龐大的整體,而函數(shù)是其一個個功能的分布,那么在java里類就是實現(xiàn)各個子模塊的實現(xiàn)者。在java的面相編程思維中,類的設(shè)計秉持高內(nèi)聚,低耦合的思想。即在每個類的內(nèi)部只關(guān)心自己類的操作,而不去關(guān)心其他類的事情。這樣的好處是,我們把整個過程細化成很多個類去實現(xiàn),每個類只需實現(xiàn)自己的功能,而不需關(guān)心其他類的功能。這樣方便程序員在寫每個模塊的時候不需考慮當(dāng)前類對其他類的影響,并且方便進行單元測試以及問題的發(fā)現(xiàn)。同時當(dāng)某個需求發(fā)生改變時,只需更改相應(yīng)的類,而不需去修改其他相關(guān)的類。因為類與類之間的關(guān)系是低耦合的。這樣方便日后的維護與調(diào)試。
    • (2)從設(shè)計安全性的角度來說,java在大型項目開發(fā)的時候更加安全。因為每個類的屬性都是private的,其他類不能直接訪問當(dāng)前類的私有屬性,因此無法直接對屬性的值進行修改。這是安全的,因為其他類可能并不知道這個類的設(shè)計原則,若直接修改類的屬性可能導(dǎo)致bug的產(chǎn)生。java針對這種情況提供了public方法,其他類可以調(diào)用public方法去實現(xiàn)類屬性的修改,而一些修改的限制都寫在方法中,因此其他類無需知道這些細節(jié),并且這些public方法也保證了類屬性數(shù)據(jù)的安全性。同時java還提供了接口的思想,即很多不同的類為了實現(xiàn)某個接口,就能實現(xiàn)類與類之間的聯(lián)系。這樣就大大增加了程序的可擴展性和可移植性。
    • (3)java還有一個很大的優(yōu)勢就是其寫法相當(dāng)簡便,相比于c它提供了大量的內(nèi)置函數(shù)包以供調(diào)用,比如其String類,ArrayList類,HashMap類等等。還有一些sort,find函數(shù),這些函數(shù)都是經(jīng)過優(yōu)化的方法,省去了程序員一些復(fù)雜地基本操作,使程序可讀性增強。

二、多項式求導(dǎo)程序設(shè)計說明

  • (1)第一次作業(yè)
    第一次作業(yè)的設(shè)計,現(xiàn)在看來真是雜亂不堪,完全是面相過程式編程,只不過是套了一個JAVA的殼子而已,存在很多的問題。
    第一次作業(yè)的題目是求一個簡單多項式的導(dǎo)數(shù)。所有的表達式都是形如\(f(x) = \Sigma a*x^c\)這種形式。這個多項式是一個字符串類型,當(dāng)然我們首先應(yīng)該判斷其是否合法。我的思路是首先通過正則匹配檢查是否存在不合法的空格。

    String pattern1 = ".*[+-]\\s*[+-]\\s+\\d.*"; String pattern2= ".*[\\^]\\s*[+-]\\s+\\d.*"; String pattern3 = ".*\\d+\\s+\\d+.*";

    上述的三個表達式分別判斷了是否存在表達式加法時的帶符號整數(shù)之間的非法空格,數(shù)字與數(shù)字之間的非法空格,以及指數(shù)后的帶符號整數(shù)的非法空格。在判斷不存在這樣的非法空格之后,為了方便后續(xù)的項的分離,我們將字符串中的所有空格和\t制表符全都刪去。
    然后我們對整個字符串進行合法性的檢驗,檢查其每一項是否都屬于\(f(x) = a*x^c\)這種形式。這里的正則表達式如下。

    pattern1 = "([+-]{0,2}(((\\d+[*])?[x]([\\^]([+-])?\\d+)?)|(\\d+)))";

    我們這里需要注意,因為其是貪婪性匹配,每次都去匹配滿足上述模式的最大字符串,因此當(dāng)字符串巨大時可能會存在爆棧的情況,因此我們調(diào)用Pattern Matcher里的方法將其分成一個個小的GROUP,并得到每個表達式的系數(shù)以及指數(shù),并將其存在多項式類中

下面是第一次作業(yè)的類圖

第一次作業(yè)的失敗主要是把所有的函數(shù)方法都寫在了一個類里面,無論是數(shù)據(jù)的讀取,還是表達式的構(gòu)造,以及最后的輸出,都是在一個Main類里,導(dǎo)致這個類的長度達到了幾百行。這是明顯違反了OO的設(shè)計準則的。正確的設(shè)計方法應(yīng)該是首先構(gòu)造一個讀取類,這個類專門用來讀取數(shù)據(jù),并且存儲我們的字符串。然后再寫一個判斷類,來判斷我們的字符串是否合法。再通過一個分離類,將我們的字符串進行分離,將分離出來的數(shù)據(jù)存儲在我們的多項式類中,最后再通過輸出類來進行數(shù)據(jù)的輸出。這樣每個模塊功能明確,并且當(dāng)日后增加需求的時候,大的模塊不需要變動,只需在各個類中添加或者修改方法即可。
  • (2)第二次作業(yè):第二次作業(yè)在第一次作業(yè)的基礎(chǔ)上增加了\(sin(x)以及cos(x)這兩種冪函數(shù)\),并且在每個表達式中允許存在兩個因式相乘的形式。由于第一次作業(yè)的偷懶設(shè)計,導(dǎo)致第二次作業(yè)的架構(gòu)需要重新設(shè)計,但是在做完第三次作業(yè)之后發(fā)現(xiàn)第二次作業(yè)的設(shè)計依舊是有很大的弊端。

    第二次作業(yè)的多項式的形式是 \(f(x)=\Sigma a*sin(x)^b*cos(x)^c*x^d\)。項里可以存在乘法,這就需要更改之前的表達式的分離的方法。首先我先更改了多項式的存儲結(jié)構(gòu),運來的多項式里只包含x的指數(shù)和系數(shù)。現(xiàn)在加入了\(sin(x)和cos(x)\)的指數(shù)。最后得到一個項的list,并且根據(jù)相應(yīng)的公式進行求導(dǎo)。求導(dǎo)的公式是
    \(a*l*x ^ (a - 1)*cos(x)^c*sin(x)^b + b*l*x^a*cos(x)*cos(x)^c* sin(x)^(b - 1) - c*l*x^a*cos(x)^(c - 1)*sin(x)*sin(x)^b\)

    這次作業(yè)在上一次的基礎(chǔ)上更新正則表達式的匹配樣例

    String patternHead = "[+-]{0,2}(([+-]?\\d+)|(" +"[x]([\\^][+-]?\\d+)?)" +"|([s][i][n][\\(][x][\\)]([\\^][+-]?\\d+)?)" +"|([c][o][s][\\(]" +"[x][\\)]([\\^][+-]?\\d+)?))([*](([+-]?\\d+)|([x]([\\^][+-]" +"?\\d+)?)|" +"([s][i][n][\\(][x][\\)]([\\^][+-]?\\d+)?)|([c][o][s][\\(]" +"[x][\\)]([\\^][+-]?\\d+)?)))*";

    通過這個表達式去得到一個個項,然后通過split
    函數(shù)將\(*\)號分開得到一個個因式,再通過因式的匹配樣例

    Pattern pattern = Pattern.compile("[+-]{0,3}[0-9]+"); Pattern pattern = Pattern.compile("([+-]{0,2})[x]([\\^]" +"?(([+-]?)(\\d+)))?"); Pattern pattern = "([+-]{0,2})sin[\\(]x[\\)]([\\^]([+-]?\\d+))?"; Pattern pattern = "([+-]{0,2})[c][o][s][\\(]x[\\)]([\\^]([+-]?\\d+))?";

    分別得到了項的系數(shù),\(x的指數(shù),sin(x)的指數(shù),cos(x)的指數(shù)\),然后存入我們的結(jié)構(gòu)體中。最后通過上述求導(dǎo)公式對每個項進行求導(dǎo),并且將相同系數(shù)的項合并。
    類圖如下

    可以看到其實第二次設(shè)計依舊沒有秉持好的設(shè)計原則,雖然將不同的功能寫在不同的方法里,但是沒有實現(xiàn)類的分類,這里好的設(shè)計應(yīng)該是sin(x),cos(x),x單獨分類,然后進行求導(dǎo),以及輸出。然而這里混在了一起,導(dǎo)致main方法十分龐大,修改一個地方會導(dǎo)致很多方法都需要修改。因為代碼之間的耦合度非常高,并且?guī)缀跛械牟僮鞫际菍懺赑oly里的靜態(tài)方法,導(dǎo)致第三次作業(yè)又需要進行大規(guī)模的重構(gòu)。

  • (3)第三次作業(yè)
    這次作業(yè)是我三次里認為還比較滿意的一次作業(yè),因為這次的題目比較復(fù)雜,因此我覺得不能再像前兩次作業(yè)那樣急于編寫代碼,因為這樣會導(dǎo)致代碼紊亂,最后難以找bug。因此在動手寫代碼之前,我仔仔細細地參照面相對象編程的思想,對第三次的題目進行了思考,先把類和接口設(shè)計好再進行動手編寫代碼,果然想清思路之后再下手,寫起來快并且最后的bug也少了,代碼思路非常清晰。

    簡單分析一下這次的作業(yè),這次的多項式求導(dǎo)不僅延續(xù)了之前的項的思路,還添加了嵌套求導(dǎo)的規(guī)則。即

    表達式 = 項{+項}項 = 因子*{因子}因子 = (表達式)|因子

    也就是類似\(sin(cos(x))\)這種嵌套的求導(dǎo)。我知道再延續(xù)以往的面相過程求導(dǎo)肯定是行不通的了。因此這次的設(shè)計對每一步進行了細致的類的劃分。類圖如下。

    下面來講一下我的做法,首先我這次劃分了很多個類,常數(shù)類、x項類、cos項類、sin項類、指數(shù)項類、加法類、乘法類這些類,這些類都實現(xiàn)了一個求導(dǎo)的接口,也就是說所有求導(dǎo)的對象都是另一個可求導(dǎo)的對象,比如說指數(shù)類里,指數(shù)的底數(shù)也是一個實現(xiàn)了求導(dǎo)的類,這樣就很好地體現(xiàn)了分類的思想,并且在指數(shù)這個類里,我只需管指數(shù)函數(shù)是如何求導(dǎo)的,而不需要管其底數(shù)是什么,因為底數(shù)實現(xiàn)了求導(dǎo)接口,底數(shù)也會自動去調(diào)其覆寫的求導(dǎo)方法去對底數(shù)進行求導(dǎo)。這樣就使我們的程序顯得很簡單。
    這里的加法和乘法類就是指兩個實現(xiàn)了求導(dǎo)接口的對象相乘進行求導(dǎo),我們只需關(guān)心乘法的求導(dǎo)是怎么樣的,而具體對象的求導(dǎo),放在具體的對象的求導(dǎo)里去完成,這樣就真正實現(xiàn)了低耦合的思想。

    具體的接口的代碼如下:

    public interface Derive { public abstract Derive derive();//求導(dǎo)函數(shù)public abstract void print(); }

    然后乘法里實現(xiàn)的求導(dǎo)接口的求導(dǎo)方法如下。

    public Derive derive() {ArrayList<Derive> addList = new ArrayList<Derive>();for (int i = 0; i < this.list.size(); i++) {/** 根據(jù)幾個函數(shù)連乘的求導(dǎo)法則進行求導(dǎo)* result = (ui' * (u1*u2*....un)/ui)的和*/ArrayList<Derive> multList = new ArrayList<Derive>();for (int j = 0; j < this.list.size(); j++) {if (i != j) {multList.add(this.list.get(j));}}multList.add(list.get(i).derive());Mult mult = new Mult(multList);/*** 這條multList 就是Add鏈中其中的一條**/addList.add(mult);}/*** 至次為止, addList是由好幾個Mult類構(gòu)成*/return new Add(addList);}

    我們可以看到,對于\(f(x) = h(x)*g(x)\)的求導(dǎo),只需關(guān)心\(f(x)'=f(x)'g(x)+f(x)g(x)'\)即可,而不需關(guān)心\(f(x)'和g(x)'\)是什么,因為\(f(x)和g(x)\)都是已經(jīng)實現(xiàn)了求導(dǎo)方法的對象,在他的類里會調(diào)用自己的求導(dǎo)方法進行遞歸求導(dǎo)。

    在明確了類的框架結(jié)構(gòu)以后,我們再想辦法對字符串進行處理,我一開始嘗試原來的正則文法匹配的方法,但是發(fā)現(xiàn)自己不明白如何去產(chǎn)生上述的表達式里嵌套因子的方式,但是我發(fā)現(xiàn),這個形式和我們之前學(xué)過的編譯原理的遞歸下降分析法類似。于是我采用相同的思想先寫了一個簡單的詞法分析小程序,然后構(gòu)造了expr(),term(),factor()三個子程序來對字符串進行讀取。這樣就能實現(xiàn)程序的因子里嵌套表達式的形式了。下面舉一個簡單的表達式的例子。

    /*** 自頂向下的表達式子程序*/ public static Derive expr() {/*** 表達式 = 項 {+項}*/ArrayList<Derive> exprList = new ArrayList<Derive>();Derive term1 = term();exprList.add(term1);if (!checkExprTail()) {System.out.println("WRONG FORMAT!");System.exit(0);}while (sym.equals("Add") || sym.equals("Minus")) {headFlag = 1;term1 = term();exprList.add(term1);}if (!checkTail()) {err();}return new Add(exprList); }

    這樣在后續(xù)的調(diào)試過程中我可以單獨根據(jù)每種形式的求導(dǎo)來找問題,就能很快地發(fā)現(xiàn)是哪個求導(dǎo)過程發(fā)生了問題,簡明扼要。

三:程序結(jié)構(gòu)分析

  • 各類代碼總規(guī)模:(statistic)

    SourceFileTotal LinesSource CodeSource CodeComment LinesBlank Lines
    Derive.java8431
    X.java10802
    Constant.java251906
    Sinx.java281846
    Cosx.java282035
    Mult.java5230139
    Add.java5440311
    Degree.java61361312
    Poly.java3903452124
    Total6585226076
  • 類的屬性方法個數(shù)

    類屬性方法
    Derive.java02
    X.java02
    Constant.java13
    Sinx.java13
    Cosx.java13
    Mult.java12
    Add.java12
    Degree.java25
    Poly.java814

四:程序優(yōu)缺點

  • 優(yōu)點:

    1:將復(fù)雜的多項式求導(dǎo)分成諸多形式的類,每個類只需注意自己的求導(dǎo)形式,具體的求導(dǎo)規(guī)則由各個實現(xiàn)求導(dǎo)接口的類去完成。 2:采用遞歸下降子程序法,使字符串的處理比較容易理解,并且不容易出錯。 3:使用了接口的思想,方便可擴展性。 4:實現(xiàn)了高內(nèi)聚低耦合的思想,使每個類和方法盡量能干的事情少,各自之間互不影響。
  • 缺點:

    1:在處理項的連乘的時候可能會出現(xiàn)爆棧的情況。2:沒有做完備的可能發(fā)生異常的情況的統(tǒng)計與測試。3:單元測試不夠完備,Main類的設(shè)計還過于冗雜。4:存在大量的if-else語句,不夠精煉,存在代碼復(fù)用比較嚴重。5:輸出的時候如果嵌套層次太多,會導(dǎo)致大量的()產(chǎn)生,很難進行優(yōu)化。

五:程序的Bug分析

  • 第一次

    第一次的bug在于沒有處理指數(shù)或者系數(shù)過長可能拋出的異常,沒有意識到助教和老師在作業(yè)指導(dǎo)書里的提示,這個問題在我理解了BigInteger類之后得到了較好的解決。并且在checkStyle風(fēng)格檢查的時候,沒有按照規(guī)范要求的行數(shù)以及縮進。還存在表達式第一項如果為數(shù)字的話前面的符號的個數(shù)的問題。

  • 第二次

    • 第二次的第一個小bug是未考慮Scanner異常輸入時拋出的異常會使程序crash,這里只需要在輸入的地方加上try-catch的異常處理即可。
    • 第二個bug是在去除空格的時候沒有吧制表符\t一起去除,沒有重視空格space與制表符在ASCII碼上不同的本質(zhì)區(qū)別。
    • 第三個bug是在輸出的時候,我是按照不管指數(shù)系數(shù)為不為0或1,全部將其按照\(a*x^b*sin(x)^c*cos(x)^d\)的格式輸出,然后再對字符串進行處理,去掉"+1","1","^1"這些,但是忽略了完備性,如果一個指數(shù)恰好是 \(y^12\),那么去掉\(*1*\)之后就變成了\(y2\),這明顯是錯誤的。錯誤的原因就是沒有對類進行細分,如果按照第三次作業(yè)的方式對每個函數(shù)進行分類輸出就會簡單很多,可以分別判斷系數(shù)、指數(shù)為0為1的情況,就可以省去大量的if-else并且保證程序的正確性。
  • 第三次作業(yè)

    • 沒有考慮到輸出的時候\(sin(2*x)\)這種錯誤的輸出格式帶來的問題。
    • 一開始沒有做左右括號匹配的處理。

六:自我評價與寄語

通過第一個單元的學(xué)習(xí),已經(jīng)基本掌握了各種java類的用法,也理解了面向?qū)ο蟮脑O(shè)計思想。了解了繼承與接口的原理。但是在使用上還存在不熟練的時候。希望在日后進行多線程學(xué)習(xí)之前,能夠把java的基礎(chǔ)打扎實,寫出漂亮穩(wěn)定的好程序。

轉(zhuǎn)載于:https://www.cnblogs.com/somnus-chen/p/10591953.html

總結(jié)

以上是生活随笔為你收集整理的OO第一次单元总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。