1.前言:
第四次題目集:
這次題目集的第一和第二個題目比較簡單,很容易可以做出來,只是用到了一個新的知識點——繼承,繼承(Inheritance)是物件導向程式設計的核心特性之一。它允許一個類(子類)繼承另一個類(父類)的屬性和方法,從而實現程式碼複用和功能擴充套件。繼承是透過extends關鍵字來實現的,子類可以繼承父類的所有非私有(private)成員變數和方法。在子類中,可以透過super關鍵字訪問父類的成員變數和方法,父類的建構函式不會自動被子類繼承,但可以透過super()在子類建構函式中顯式呼叫父類的建構函式,所以super關鍵字不僅可以用來訪問父類的方法和變數,還可以用於呼叫父類的建構函式。而當子類需要修改父類的方法時,可以使用方法重寫(@Override),在子類中重新定義與父類方法相同簽名的方法,子類的方法會覆蓋父類的方法,這樣就可以指向明確,方便使用,使相同的方法不同的類達到不同的效果。對於第一二題,只需要用extends和super關鍵字就能完成。而第三題就比較複雜了。在之前題目的基礎上選擇題和填空題,選擇題還包括單選和多選,無疑使題目複雜度更上一層樓。
第五、六次題目集:
從這倆次題目開始就是另一個新題目的迭代設計了,是一個居強電電路模擬程式。主要功能是計算電壓和調節裝置並顯示裝置資訊。題目思路是設計電路裝置主父類,繼承了受控裝置類、控制裝置類、串聯裝置類、並聯裝置類。在受控裝置類和控制裝置類裡編寫各種裝置資訊,而在串並聯電路寫裝置之間的連線資訊和調整資訊以及引數的計算。還有輸入輸出類,輸入類是解析輸入資訊,輸出類是保證輸出的準確性和正確性。是對繼承這一核心知識點的運用和理解,題量和複雜性是比較大的,對我來說是需要花費大量時間來寫的。
2.設計與分析
第四次題目集-答題判題程式-4
(1)類圖
(2)圈複雜度
1.程式碼結構
類結構:
Question:表示一個題目,包含ID、內容、答案和型別。
TestPaper:表示一份試卷,包含ID和題目列表。
QuestionScore:表示題目的得分資訊。
Student:表示一個學生,包含ID和姓名。
AnswerSheet:表示一份答題卡,包含試卷ID、學生ID和答案。
資料結構:
questions:儲存所有題目,鍵為題目ID。
testPapers:儲存所有試卷,鍵為試卷ID。
students:儲存所有學生,鍵為學生ID。
answerSheets:儲存所有答題卡。
deletedQuestions:儲存已刪除的題目ID。
方法:
main:主入口,讀取輸入並處理。
processInput:根據輸入型別呼叫相應處理方法。
processSingleChoiceQuestion、processMultipleChoiceQuestion、processFillInBlankQuestion:處理不同型別題目的輸入。
processTestPaper:處理試卷的輸入。
processStudent:處理學生的輸入。
processAnswerSheet:處理答題卡的輸入。
processDeleteQuestion:處理刪除題目的輸入。
calculateTotalScore:計算試卷總分。
outputTestPaperAlert:輸出試卷分數不為100的警告。
outputStudentResult:輸出學生的答題結果。
outputResults:輸出所有結果。
第五次題目集-家居強電電路模擬程式-1
(1)類圖
(2)圈複雜度
- 程式碼結構
Main 類:程式的入口,負責初始化 Scanner 和 Input 類,並呼叫 scanf 方法處理輸入。
Input 類:處理從標準輸入讀取的資料,包括連線資訊和裝置調節資訊。
SeriesCircuit 類:表示一個串聯電路,包含裝置管理、電壓更新、狀態更新和裝置顯示等功能。
ControlEquipment 介面:定義了裝置的基本操作,如調整裝置狀態。
具體裝置類:如 Switch、GearSpeedRegulator、ContinuousSpeedRegulator、IncandescentLamp、FluorescentLamp 和 CeilingFan,實現了 ControlEquipment 介面。
2.解釋與心得
(1)根據符號的不同,分別建立裝置
這段程式碼透過使用 switch 語句,根據裝置名稱的首字母來動態建立不同型別的裝置物件,結構清晰且易於理解。它的優點在於:
1)清晰簡潔:switch 語句將不同裝置的建立邏輯清晰地劃分為多個分支,使得程式碼易於閱讀和理解。每個裝置型別的邏輯都對應一個明確的 case,避免了混亂和複雜的條件判斷。
2)易於擴充套件:如果將來需要支援更多裝置型別,只需在 switch 語句中新增相應的 case 分支,不需要修改現有程式碼的其他部分。這樣使得程式碼具備了良好的可擴充套件性。
3)集中管理:所有裝置的建立邏輯都集中在 createDevice 方法中,便於後續的修改和維護。如果建立裝置的邏輯發生變化,只需要在此方法中做調整,減少了分散修改的複雜度。
4)高效執行:相比於多個 if-else 語句,switch 語句在處理多個條件判斷時通常會被編譯成查詢表或最佳化後的跳轉程式碼,提供更高的執行效率,尤其在條件判斷較多時效能優勢更加明顯。
5)減少冗餘:透過集中管理裝置建立邏輯,避免了程式碼中硬編碼或重複的判斷條件,使得程式碼更加簡潔,減少了冗餘部分,提高了程式碼質量和可維護性。
總的來說,這段程式碼透過 switch 語句實現了裝置建立的高效、清晰、可擴充套件的邏輯,是一種良好的程式設計實踐,適合於長期維護和擴充套件,如果之後還有別的裝置需要建立,直接加個case就行,十分方便。
(2)對於輸入的判斷
不是把判斷的程式碼一起寫在這裡,而是直接寫在另一個函式里,當輸入不是end時,跳轉到processInput函式里,在這個函式里寫對應得處理操作。優點在於透過使用 while 迴圈持續讀取輸入,直到遇到指定的終止條件 "end",保證了輸入處理的靈活性和可控性。每次讀取輸入時,透過 trim() 方法去除兩端空格,確保輸入資料的整潔性,並透過 processInput() 方法對每一行輸入進行處理,增強了程式碼的模組化和可維護性。整體邏輯簡潔高效,能夠適應動態輸入,具有較好的擴充套件性和易於理解的結構。
第六次題目集-家居強電電路模擬程式-2
(1)類圖
(2)圈複雜度
1.程式碼結構
Device 類:抽象基類,包含裝置的基本屬性和方法。
具體裝置類:如 GearSpeedRegulator、ContinuousSpeedRegulator、Switch 等,繼承自 Device 類,實現具體的功能。
SeriesCircuit 類:表示串聯電路,包含多個裝置,可以新增裝置並執行操作。
ParallelCircuit 類:表示並聯電路,包含多個串聯電路,可以設定輸入電壓並執行操作。
裝置速度調節:透過 adjust 方法調整齒輪調速器的速度。
連續調速器位置調整:透過 setPosition 方法設定連續調速器的位置。
串聯電路處理:解析輸入行,建立串聯電路並新增裝置。
並聯電路處理:解析輸入行,建立並聯電路並新增串聯電路。
裝置建立:根據裝置ID的首字母建立不同型別的具體裝置物件。
操作所有並聯電路:設定輸入電壓並執行操作。
列印所有裝置狀態:遍歷所有裝置並列印其狀態資訊。
2.解釋與心得
(1)提取串聯電路得裝置
processConnection 方法的主要功能是解析一個特定格式的字串(如 #T1:[IN K1-1] [K2-2 K3-1] [K4-2 OUT]),透過正規表示式提取其中的裝置資訊,並對每個裝置識別符號呼叫 processDevice 方法進行處理。首先,它使用一個正規表示式來匹配字串,匹配成功後從中提取出裝置 ID,例如 K1-1、K2-2 等。對於每個裝置 ID,它提取出識別符號部分(如 K1、K2),並傳遞給 processDevice 方法進行進一步處理。如果字串格式不符合預期,方法會輸出錯誤提示資訊“Invalid input format”。該方法透過正則匹配和提取裝置資訊來自動化處理裝置識別符號,並確保輸入符合特定格式。
(2)調整裝置狀態
這段程式碼的作用是根據不同的控制命令對裝置進行操作。它透過檢查傳入的命令字串的開頭來判斷是哪種操作,並從命令中提取相應的資訊(如裝置ID、動作型別、速度或位置)。具體地:
當命令以 #K 開頭時,表示控制裝置的開關。程式透過裝置ID查詢裝置,並呼叫裝置的 toggle() 方法切換裝置的開關狀態。
當命令以 #F 開頭時,表示調整齒輪調速器的速度。程式提取調整方向(加速或減速),並透過裝置ID找到相應的調速器,呼叫 adjust() 方法來增加或減少速度。
當命令以 #L 開頭時,表示調整連續調速器的位置。程式從命令中提取新的位置值,並呼叫 setPosition() 方法設定該位置。
對於每種操作,程式碼都會檢查裝置是否存在於 devices 集合中,如果存在,則執行相應的操作。
3.踩坑心得
(1)對於大量裝置的處理,可以考慮使用更高效的資料結構,如 HashMap 來儲存裝置,提高查詢和更新的效率,同時HashMap 提供了豐富的 API,使得新增、刪除和查詢裝置的操作非常簡單和直觀。
實現:
public class SeriesCircuit {
private Map<String, ControlEquipment> devices = new HashMap<>();
public void addDevice(ControlEquipment device) {
devices.put(device.getDeviceID(), device);
}
public void updateVoltages() {
for (ControlEquipment device : devices.values()) {
device.adjustVoltage();
}
}
}
(2)及時更新裝置狀態,如果裝置狀態更新不及時,會導致顯示的資訊不準確。
實現:在 SeriesCircuit 類中,確保每次處理連線資訊後立即更新裝置狀態。
public void testDeviceStateUpdate() {
SeriesCircuit circuit = new SeriesCircuit("Circuit1", 1);
circuit.processConnection("[#K1]");
circuit.updateVoltages();
circuit.updateStates();
circuit.displayDevices();
assertTrue(System.out.toString().contains("@K1:0"));
}
(3)獲取裝置物件
問題:在獲取裝置物件時,需要進行型別轉換,如 GearSpeedRegulator gear = (GearSpeedRegulator) devices.get(deviceId);。
解決:確保裝置對映中儲存的物件型別正確,避免執行時型別轉換錯誤。
(4)裝置ID重複問題
問題:如果裝置ID重複,可能會導致裝置物件被覆蓋。
解決:在建立裝置時,檢查裝置ID是否已存在,避免重複建立。
4.改進建議
使用橋接模式,橋接模式(Bridge Pattern)可以使程式碼結構更加靈活,避免在單一類中大量的條件判斷,並且使得裝置控制邏輯和裝置型別的操作解耦。具體的改進方式是,將不同的裝置操作和具體裝置型別的實現分開,使得新增裝置型別或操作時,程式碼的修改不會互相影響,從而提升可維護性和擴充套件性。
改進後的優勢:
1)解耦控制邏輯與裝置型別:DeviceCommand 類和 DeviceControl 介面不再關心具體的裝置型別實現,從而解耦了命令和裝置。不同型別的裝置可以共享相同的控制邏輯。
2)易於擴充套件:若未來需要支援新的裝置型別,只需新增實現 DeviceControl 介面的裝置類,而不必修改控制命令類。類似地,增加新的控制命令(如調整溫度、方向等)也變得更加容易。
3)靈活的裝置操作:透過橋接模式,可以為不同裝置實現不同的操作方法,例如有些裝置可以調整速度,有些裝置則可能沒有調整速度的功能。
4)程式碼更加清晰和簡潔:避免了冗長的條件判斷和型別檢查,使得程式碼的可讀性和可維護性大大提高。
5.總結
隨著實驗難度的逐漸增加,題目變得越來越複雜。我深刻體會到,編寫高質量程式碼的關鍵不僅在於技術層面的熟練度,更在於有一個清晰的頭腦和合理的結構設計。面對複雜問題時,保持冷靜,理清思路,將大問題分解成小問題逐步解決。設計時採用模組化和介面分離的方法,確保程式碼的可讀性和可維護性。實現功能時,逐步推進,編寫單元測試和整合測試,確保每一步都經過充分驗證。此外,清晰的思路至關重要,透過需求分析、虛擬碼和程式碼審查來確保思路的正確性。透過不斷的實踐和學習,積累經驗,提高解決問題的能力。希望這些總結和反思能夠幫助我在未來的開發過程中不斷提升,更好地應對複雜的程式設計挑戰。最關鍵的是要預留充足的時間來寫程式碼,不要留到週末來寫,每次時間緊張的時候,我都會靜不下心來寫程式碼,再加上程式碼確實難,總會造成不好的結果。所以,最好前幾天就能寫好程式碼框架,實現部分樣例的測試透過,然後最後幾天,再一步步透過剩下的測試點,完善程式碼邏輯。