1. 程式人生 > 其它 >OOP課程第三階段總結Blog

OOP課程第三階段總結Blog

------------恢復內容開始------------

OOP課程第二階段總結Blog

20201328-嚴振軒

前言:學習OOP課程的第三階段已經結束了,而OOP課程也已經接近尾聲。本階段的學習體現出敏捷式迭代程式設計學習的形式,作業與作業間有充分聯絡。以下是我對本階段學習總結以及題目分析。

(1)題目集7作為本階段的開篇,通過兩道圖形卡片遊戲程式設計題目對前一階段學習到的繼承與多型進行了複習運用。以及學習到了ArrayList的使用方法,並通過此方法,物件的新增以及資料處理有了更為高效的運用。新的程式設計思路的運用在於:“開-閉”原則以及單一職責原則的運用,通過兩道題目迭代,同時知識的更新使用,為後續題目集有了更多的程式設計思路啟發。難度而言,通過率較高,屬於新知識,易學,並通過老師給的類圖,可以較為輕鬆完成作業。

(2)題目集8題目量少,僅一道,難度卻是不一樣的大。因為這一次的需要我們通過ATM機業務背景自己去設計類間關係,題目本身邏輯簡單,考察在實體類,業務類的設計,以及為後續迭代拓展,需要遵守程式設計的“開-閉原則”以及為將後續新增功能,需要做到設計嚴謹,對於自己拓展的類也需要遵守“單一職責原則”,總體而言是難度較大的一次作業,需要真正去自己動腦設計,而不是單純的根據他人的類圖程式設計。

(3)題目集9題量同樣也為一道。題目形式也為ATM機類機構設計。本次添加了貸記以及透支取款的功能。本次作業是需要在老師提供的原始碼上進行功能新增以及本身原始碼的完善。進行了抽象類,多型,繼承的運用。雖是之前就運用過的方式,本次需要我們主動去想到在什麼方面進行使用。高質量符合題目要求的原始碼完成,需要對以上知識點有充分的認識與吸收。此題目本身功能性不復雜,需要我們去做到類的關係調用以及設計類功能是難度所在。

各題目 設計與分析 採坑心得 改進建議 :

(1)題目集7:(7-1)圖形卡片排序遊戲 (7-2)圖形卡片分組遊戲 遞進式設計分析總結

設計與分析

7-1 類圖以及複雜度分析圖

7-2 類圖以及複雜度分析圖

就7-1而言,本次為圖形卡片排序遊戲,通過設計出一個抽象Shape類,進而對Shape進行拓展出三角形,圓形,矩形,梯形類,其中在主類進行物件合法性的檢驗以及對應圖形數量的新增。在不同的主體類中有著大致相同的方法:求面積,合法性校驗,Set,Get方法,在DealCardList業務類中進行對對應具體圖形類屬性的新增,進而將實體類與業務類聯絡起來。實體類都繼承於Shape類中。而在程式碼中設計了求面積的介面類,實現了求面積的多型。功能體現在對輸入的圖形進行求面積處理,其次進行了排序,最後求出面積總和。對於多物件情況,採用存在ArrayList中進行流水線式的處理,使程式碼更為簡潔,不需要一個個判斷後再進行新增。設計遵守了單一職責原則以及“開-閉”原則,便於7-2題目的拓展功能新增。

就7-2而言,本次為圖形卡片分組遊戲,該次作業是對7-1題目的迭代,新增的功能有:對初始求出的面積資料進行分組;對分組後的資料在組內進行排序;得到全部圖形中的最大面積。實體類設計與7-1無差別,主要使DealCardList業務類中,需要進行更為細緻的分組處理。首先在DealCardList類中添加了幾種Boolean型方法,判斷語句採用了匹配字串的equals語句,進行初步的分類校驗。通過建立四種方法,將不同的四種圖形的輸出方式表示為一種長字串進行輸出,每確定一種圖形的種類,以及算出對應面積之後,則將新確定的字串拼接在之前的字串後一位,以card順序i作為迴圈上限,將每次i對應的圖形一個個進行校驗,以確定在對應輸出位置上。排序方法上選擇了插入排序,並且程式碼的迴圈語句採用的增強for迴圈。在求最大面積上,將card的i作為迴圈依據,通過比較得出最後的最大面積的值,本次作業難度不算大,但需要細緻的類間關係調用,才會使程式碼更簡潔可觀。而對於ArrayList的使用同樣也十分重要,物件的處理因此更為高效。

採坑心得

7-1題目中程式碼:

7-2題目中程式碼:

7-2主類開始的程式碼中較7-1不同的地方是需要先進行一次開始輸入的n是否是0的判斷,在7-2測試點的要求中,需要對第一個n有特殊的判斷,若一開始的n就為0,則需要直接結束程式並輸出Worry Format。在一開始進行7-2程式碼編寫時,並沒有刻意注意這個問題,導致個別測試點無法通過,後通過測試找到了問題,並完成了程式碼補充。

public String Circle1() {
        String str = "";
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Circle"))
                str+="Circle:"+String.format("%.2f",i.getShape().getArea()) + " ";
        }
        return str;
    }
    public String Rectangle2() {
        String str = "";
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Rectangle"))
                str+="Rectangle:"+String.format("%.2f",i.getShape().getArea()) + " ";
        }
        return str;
    }
    
    public String Triangle3() {
        String str = "";
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Triangle"))
                str+="Triangle:"+String.format("%.2f",i.getShape().getArea()) + " ";
        }
        return str;
    }
    
    
    public String Trapezoid4() {
        String str = "";
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Trapezoid"))
            str+="Trapezoid:"+String.format("%.2f",i.getShape().getArea()) + " ";
        }
        return str;
    }

該部分的程式碼是為後續分組的呈現所額外書寫的。一開始對於分組的實現想的是通過遍歷後對i對應的CardName進行equals檢驗字串,再建立四鍾List儲存得到的分組結果。後發現該種思路的書寫過於亢長且邏輯混亂,程式碼再eclipse中得到了正確結果,在PTA中因程式碼長度限制,從而更改了思路,直接採用四種方法遍歷,去匹配到組別以及位置。

double max = 0;
        double sum = 0;
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Circle"))
            sum+= i.getShape().getArea();
        }
        if(sum > max) {
            max = sum;
        }
        sum = 0;
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Rectangle"))
            sum+= i.getShape().getArea();
        }
        if(sum > max) {
            max = sum;
        }
        sum = 0;
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Triangle"))
            sum+= i.getShape().getArea();
        }
        if(sum > max) {
            max = sum;
        }
        sum = 0;
        for(Card i:cardList) {
            if(i.getShape().getShapeName().equals("Trapezoid"))
            sum+= i.getShape().getArea();
        }
        if(sum > max) {
            max = sum;
        }
        sum = 0;
        System.out.print(String.format("%.2f",max));

該部分程式碼為求面積和最大值的功能。初始設計時對於題目理解錯誤,認為是求單個圖形的面積最大值,所寫出的for迴圈更多,遍歷的時間更長。後發現無法通過大多數的測試點,通過PTA測試點分析,得到是題目理解出了問題,刪減了一部分程式碼後,新增的if語句找到了圖形面積和最大值。並得到了對應的輸出。

改進建議

1.改進點更多在類中方法的設計以及功能演算法設計上。在7-1中,對於排序上採用的依舊是插入排序法,而也嘗試過去使用sort排序,這樣的程式碼更加的簡潔有效。後發現使用後會無法得到結果,再完成了7-2後發現,我排序的物件的card裡的i,而不是i對應的物件。所以若能將全部的排序規則改進為sort排序,則可以將程式碼更為簡潔。

2.7-2中提出了新的要求:分組,分組後排序,組面積和最大值尋找。在7-2中對於新功能的新增,更多是通過if語句與for語句進行識別,再通過新增新的方法去實現。後通過進行題目集9中ATM機設計中認識拓展性並不是通過一昧的if與for迴圈進行新增功能,可以對每個實體類進行充分的利用,拓展。本次題目中的分組問題可以通過在每個實體類中便設定一種“標籤”方法,標籤方法有統一的介面,在分組的過程中,通過圖形物件呼叫該方法去確定屬於哪一類並只和同一種圖形標籤的物件輸出在一個[]之中。

3.求組面積和的功能上,不需要如上述寫的在分組之後,再重複遍歷去求和,再進行組與組之間的比較。可以在分組的時候,便同時進行面積的加合,待全部的圖形面積完成了對應的分組,也同時完成了面積和的運算。

4.對於面積和最大值的尋找,不需要再進行多次的for迴圈與if判斷,再建議3的基礎上,最後進行一次sort排序便能得到最大值,直接進行結果的輸出。

遞進式設計分析總結

兩次作業帶來的感覺就是面向物件設計在新增功能上的技巧性與規範性十分重要。若為了新增功能反覆的使用if語句以及for語句,則是面向過程程式設計的設計思路,雖然可以同樣實現功能但是若資料龐大,則難以進行功能的新增與資料的處理。所以從迭代遞進的設計來看,需要從初始屬性,功能設計的開始就要遵循“開-閉”原則以及單一職責原則,為了類可以進行擴充,為了類單一定向功能的實現,使得後續維護或者功能新增有方向可找,不會盲目在業務類中進行方法的堆疊。在兩次卡片遊戲中,收穫了對ArrayList儲存物件並呼叫物件實現的方法的熟悉使用,不僅可以符合面向物件設計的原則,也可以在新增類功能上,完全進行適應,通過列表物件呼叫方法,可以高效可觀的完成對應的任務。最多的是對類似於:排序法,基本語法,基本演算法,物件建立,add方法等基礎方法綜合使用,成功的迭代是在原本程式碼的基礎上做對應功能的新增,而不需要大面積更改,對此我仍需要學習如何真正踐行“開-閉”原則。

(2)題目集8:(7-1)ATM機類結構設計(一) 題目集9:(7-1)ATM機類結構設計(二) ATM機模擬題目的設計思路分析總結

設計與分析

7-1 類圖以及複雜度分析圖

7-2 類圖以及複雜度分析圖

就題目集8的7-1而言,該題目用於設計一個簡單的ATM機功能,功能作用在:簡單的存取款與查詢餘額。設計的背景為:中國銀聯,中國銀行,銀行使用者,銀行賬戶,銀行卡,ATM機。該背景的各個組成部分,都可以實現為一個實體類。各個實體類之間有一定的關聯性,其中例如:各個中國銀行組成了中國銀聯,而中國銀行裡有著不同的銀行使用者,銀行使用者擁有自己獨立的銀行賬戶,而銀行賬戶通過銀行卡進行操作,ATM機作為銀行服務於使用者的機器,聯絡著銀行與賬戶等。需要設計出聯絡緊密且又實效的類間關係。實體類需要自己去考慮到類間的關係,而業務類則需要根據使用者的需求設計不同的功能。例如實現不同輸入情況下做到的存取款,以及查詢餘額的功能。我的程式碼在Verifcation類中作為業務類,在該類中完成不同的功能。在該類中首先構建了屬於自己的資料儲存庫,保證呼叫對應賬戶或者銀行卡號不會錯亂,以及餘額的每次更新都會得到改變。在主類中利用正則表示式對輸入的情況進行不同的分支走向,比如通過空格分隔元素得到是存取款還是查詢餘額。後又會在Verifcation類進行不同的資料的校驗:卡號,ATM編號,密碼,金額合法,是否跨行。通過合法校驗的資料則進行資料處理,通過依次對應的if語句,對輸入結果進行完善,存取金額則是簡單的加減法,只需要完成了輸入內容的其他部分,直接呼叫存取金額的方法直接填入資料即可。最終輸出是通過將一步一步的中間輸出作為字串儲存在一個字串陣列之中,在主類的最後同一個for迴圈全部進行輸出。以上是ATM機設計(一)的設計思路。

就題目集9的7-1而言,本次的程式碼是在老師給的程式碼的基礎上進行功能的新增與優化。考察的依舊是:繼承,多型,抽象類,類間關係設計以及對於“開-閉”原則,單一職責原則的掌握。跟題目集8的7-1有所不同的是新增一種信用卡,可以進行貸記操作,以及銀聯有了超額度的服務費扣取功能,跨行收費。該功能的新增與對本身程式碼的優化修改是難點。難在不知在哪進行修改,不知如何新增在恰當位置,且易將本來具有簡單功能的程式碼解構,難以保證質量。以下進行程式碼結果i有分析:首先使用者資料的匯入通過在主類裡分別進行對使用者資訊,賬戶資訊,銀行卡,借記卡資訊,以及ATM,銀行,銀聯資訊的新增,也就是利用add方法進行物件新增。以及進行雙向繫結,將物件與物件之間的聯絡更為緊密,也方便進行呼叫。在該程式碼中,我設計了賬戶父類與卡父類,以下有借記賬戶子類,信用賬戶子類以及借記卡與信用卡的子類。通過構造統一的卡類,其中包含著兩種子卡類,賬戶類同理。主類中依舊是根據正則表示式以及if語句決定功能走向的分支。對於新新增的透支與跨行的功能,分別將跨行利率作為對應銀行的屬性,將透支服務費收取金額的利率作為銀聯的屬性。當判斷需要收取對應費用時,可以直接呼叫對應的屬性即可。例如在某ATM機上跨行取錢,則通ATM機號找到對應的銀行,呼叫該銀行的利率屬性進行收費的計算。其中在功能計算中,通過instanceof方法對不同類別的賬戶進行不同的超出額度輸出判斷。本題需要額外考慮的有:跨行判斷後跨行情況的收費處理,以及透支收費,剩餘金額的實時更新以及更新後判斷是否超出額度。這些都是在通過不同類負責不同的判斷依據與功能操作得到的最後結果。最後的輸出通過while迴圈實現。以上是ATM機設計(二)的設計思路。

採坑心得

該部分為判斷取款金額是否大於餘額的判斷,以及對判斷結果對應的資料處理。其中容易掉入的陷阱是,若金額已經達到了透支,則不適用money = amount的資料處理。一開始設計單純的採用單一的資料處理,後測試點部分無法通過,進行了透支測試後發現了問題。

該部分程式碼進行對賬戶的型別判斷,進而對對應賬戶進行不同的賬戶餘額檢驗,例如借記賬戶僅用考慮10000的上限,而信用賬戶擁有貸記的功能,有50000的透支上限,兩類不同的餘額檢驗需要分開進行判斷。

該部分為跨行處理後,需要在原本的金額上額外扣除跨行的額外收費,原本程式碼過於亢長,需要先得到ATM對應的銀行,後計算得到需要額外繳付的跨行收費。而該一個if語句就足夠完成跨行判斷以及跨行收費的增加。

對於類的設計來看,設計中有卡父類以及賬戶父類,以及往下分支:信用卡類,借記卡類,信用賬戶類,借記賬戶類;這樣的設計符合繼承,且處理起來符合多型,無需在主類刻意區分兩種卡類,在資料處理中會在各自類中呼叫特有的方法進行功能的實現。起初未這樣設計,程式碼亢長且難以對多資料進行處理,不符合繼承與多型,更改了類的設計後,更具邏輯性與拓展性。

改進建議

1.在判斷是否是貸記賬戶類還是借記賬戶類上,這一步如可以不用進行類的判斷,設計一個統一的介面進行同名方法處理,則更可體現出多型性。也延續了程式碼的可拓展性以及可維護性。

2.業務類過於繁重,可以通過設計兩個業務類,一是資料校驗判斷業務類,而是資料處理業務類,這樣更可以體現出程式設計的單一職責原則。

3.在賬戶之間設定可聯絡的類,可為後續設計轉款功能作為基礎,或是在資料處理類中新增方法去完成轉款功能。

ATM機模擬題目的設計思路分析總結

題目集8的7-1用於設計一個簡單的ATM機功能,功能作用在:簡單的存取款與查詢餘額。設計的背景為:中國銀聯,中國銀行,銀行使用者,銀行賬戶,銀行卡,ATM機。該背景的各個組成部分,都可以實現為一個實體類。各個實體類之間有一定的關聯性題目集9的7-1而言,本次的程式碼是在老師給的程式碼的基礎上進行功能的新增與優化。考察的依舊是:繼承,多型,抽象類,類間關係設計以及對於“開-閉”原則,單一職責原則的掌握。跟題目集8的7-1有所不同的是新增一種信用卡,可以進行貸記操作,以及銀聯有了超額度的服務費扣取功能,跨行收費。主類中都是根據正則表示式以及if語句決定功能走向的分支。不同點在於會在題目集9的程式碼中不同的銀行新增不同的利率屬性,在業務類中新增對跨行後的收費處理以及透支判斷等。以上都是對特定功能的新增,需要考慮到類設計的“開-閉”原則,單一職責原則。以及迭代到的不僅是相同背景內容的功能新增,更有考慮到類間關係,去充分利用實體類的屬性繫結以及方法呼叫。業務類中整合方法去實現最終輸出的效果。本次ATM機迭代程式設計,本身邏輯層面簡單,注重的是嚴謹的設計思想與正確的面向物件程式設計思維。

大總結

本次階段的三次作業,更多的是對所學類設計的應用,主要是對兩種原則的掌握:“開-閉”原則,單一職責原則。以及對於“封裝性,繼承,多型,複用等”需要有自己的理解去很好的利用。對於設計的想法,面向物件設計的初衷在於將處理的事情物件化,物件要求什麼功能,我們便需要去滿足它。在這一階段的學習中,對於作業難度並不是以往的設計好的演算法去實現,前幾次階段的題目更像是套著面向物件的殼去用電腦完成數學題。這一階段本身題目邏輯並不複雜,考察的是我們對於一個事物去實現,我們該如何去做的一個好的設計,設計圍繞著可維護,可拓展,以及後續根據原始碼去新增功能,都在讓我們學習並實際去運用著面向物件程式設計的設計思想。對於後續需要學習的介面設計,需要掌握JavaFx,為此也在進行相關的學習,不斷學習,也在不斷回顧學到的內容。並且會進行深度的挖掘,更好的去理解面向物件設計的內涵。

再次感謝這一階段的學習,即將進入尾聲的面向物件設計的課程,學到了以面向物件的思想去進行程式設計,也是作為軟體工程專業的入門基礎。感謝老師與助教的工作,也要感謝堅持到現在的自己!自信的向下一階段出發!