南昌航空大學-22207107-胡優樂-Java第二次Blog大作業

嘻嘻嘻嘻xixi發表於2024-11-23

前言

 在這段時間裡,我們總共進行了三次大作業練習,基於這三次大作業的體量及設計的知識點,難度分佈,我做了以下的總結:
   1.第四次大作業總共有三道題,分別是:1.校園角色類設計-1;2.設計一個學生類和它的子類-本科生類;3.答題判斷程式-4;實際做下來的體會是:
  (1)第一題難度入門級別,涉及的知識點是:類與繼承;多型的表現形式;構造方法等;
  (2)第二題難度入門級別,涉及到的知識點是:類與繼承;構造方法;方法重寫;靜態方法的使用;輸入與字串處理;多型的表現形式等;
  (3)第三題難度為困難級別,涉及的知識點是:類與繼承;集合的使用;正規表示式;介面與排序;字串處理;異常處理;多型性的體現等;

  2.第五次大作業共有兩道題:
  第一題 家居強電電路模擬程式-1 難度級別:困難;涉及的知識點有:類的定義與抽象;繼承關係與程式碼複用;介面與排序;多種集合型別的運用;正規表示式;條件判斷與迴圈結構等;
  第二題 閱讀程式除錯改正程式 難度級別:入門; 涉及的知識點有:類與物件;封裝性的運用;集合的運用等;
  
  3.第六次大作業共有一道題:
  家居強電電路模擬程式-2 難度級別困難;涉及的知識點有:類的定義與抽象;繼承關係與程式碼複用;介面與排序;多種集合型別的運用;正規表示式;條件判斷與迴圈結構等;

設計與分析

1.答題判斷程式-4
1.類的設計:

 1.1整體類結構和層次關係

 基礎類與繼承體系構建:程式碼構建了一個圍繞考試相關業務的類層次結構,
 以Matter類作為基礎類,它抽象地描述了題目相關的通用屬性,如題目編號(qusid)、題幹(qustent)、正確答案(correctAnswer)以及題目是否正確的標識(judgeRight)。

  在此基礎上,透過繼承關係派生出了ManySelectMatter(用於表示多選題)、TianKongMatter(用於表示填空題)等子類,這些子類複用了Matter類的屬性和構造方法,同時又根據自身題型特點在這個繼承體系中佔據特定位置,體現了物件導向中透過繼承實現程式碼複用和對不同型別題目進行分類抽象的設計思路。
關聯類的協作:除了題目相關的類,還有諸如Examination類用於管理試卷中題目與分數的對映關係、Answer類用於表示學生的答案資訊,包含了學生答題的具體內容以及對應的試卷和學生編號等;Pupil類則簡單封裝了學生的基本資訊(學生編號和姓名)。
這些類相互協作,服務於整個考試資料處理的流程,例如Answer類會關聯到Pupil類(表示是哪個學生的答案)、Examination類(對應哪張試卷的答案)以及透過題目編號間接關聯到Matter類(答案對應的具體題目)。

1.2 各個類的職責與功能設計

Matter 類及其子類:

  Matter 類:作為基類,它的主要職責是封裝題目共有的基本屬性,並提供相應的訪問方法(如returnQustent、returnQusid等)以及設定題目正確與否的方法(setIsRihgt),將題目相關的資料進行統一管理,對外提供獲取和修改這些資料的介面,使得外部程式碼可以按照規範的方式與題目物件進行互動。

  ManySelectMatter 和 TianKongMatter 子類:這兩個子類繼承自Matter類,在功能上它們複用了父類的屬性和構造方法初始化流程,但從業務角度來說,它們代表了不同的具體題型,各自沒有額外新增獨特的屬性(只是複用了父類屬性來滿足自身題型需求),其存在更多是為了在整個系統中明確區分不同型別的題目,便於後續根據題型進行不同的處理邏輯,比如在判斷答案正確性等環節可以針對不同題型執行不同規則。

  Examination 和 Exam 類:
Examination 類:重點關注試卷中題目與分數的對應關係,透過LinkedHashMap<Integer, Integer>來儲存這種對映,提供了新增題目及對應分數的方法(addMatter)以及計算試卷總分的方法(calculateFullPoint),職責在於維護試卷的分值結構,方便後續基於分值進行各種統計和計算工作。

  Pupil 類:相對簡單,主要就是對學生的基本身份資訊(學生編號和姓名)進行封裝,提供對應的獲取方法(getPupilID和getName),作為整個系統中識別學生個體的基礎類,為其他類(如Answer類關聯學生)提供基本的學生資訊來源。

  JudgeManychoice 類:這個類的功能比較單一且聚焦,主要用於處理多選題答案判斷的邏輯,提供了choiceJudge方法,透過比較兩個字串陣列(代表正確答案集合和學生作答答案集合)來判斷答案的正確性,返回"true"(完全正確)、"partially correct"(部分正確)或"false"(錯誤)等結果,為在判斷學生答案是否正確的環節中針對多選題的情況提供了專門的判斷邏輯支援。

  ScannerParser 類:該類主要負責對輸入的字串按照特定格式進行解析,並根據不同的格式標識將解析後的資料儲存到對應的集合物件中,起到了輸入資料格式校驗與初步處理的作用,是整個程式中對接外部輸入資料的關鍵環節。

  WorkoutOutput 類:主要用於根據學生的答題情況、對應的試卷資訊以及題目相關資訊等,計算並輸出學生的考試結果,是整個程式中對處理後的資料進行展示呈現的重要部分,將內部資料處理結果轉化為直觀的、可供使用者檢視的輸出內容。

2.類圖

2.家居強電電路模擬程式-1
  1.類的設計

  1.1整體架構與類層次關係

  基礎類與繼承體系:程式碼以 HomeElectricalApparatus 類作為所有家用電器裝置類的基類,它定義了通用的裝置屬性,即裝置編號(apparatusId)和裝置型別(apparatusType),這種設計體現了物件導向程式設計中對共性抽象的思想。
  在此基礎上,透過繼承建立了多個子類,如 SpeedRegulatorApparatusType、SwitchApparatusType、ContinuouslyAdjustableApparatusType、IncandescentLightApparatusType、FluorescentLightApparatusType、FanApparatusType 等,每個子類代表一種具體型別的家用電器裝置,它們繼承了父類的屬性,並根據自身裝置的特點新增了特有的屬性和行為,構建出了一個清晰的類層次結構,遵循了繼承複用的原則,便於對不同型別裝置進行統一管理和差異化處理。
  類之間的協作關係:除了繼承關係外,不同類之間還存在著緊密的協作關係。例如,CommandHandler 類用於處理輸入的控制命令,它會操作儲存在 LinkedHashMap<String, HomeElectricalApparatus> 中的具體裝置物件(透過呼叫各子類的相應方法來實現具體功能,如開關切換、調速等操作);VoltageProcessor 類則負責模擬電壓在這些裝置間的傳遞以及根據電壓來設定各裝置的相關狀態,同樣依賴於儲存裝置物件的集合以及各裝置子類自身的方法實現功能。而 ApparatusComparatorType 類為裝置物件的排序提供了比較規則,使得在 Main 類中可以對處理後的裝置列表按照特定順序進行展示,這些類相互配合,共同實現了對家用電器裝置的管理、控制以及狀態展示等功能,形成了一個相對完整的功能體系。

  1.2各個類的詳細分析

  1. HomeElectricalApparatus 類
    職責與功能:作為基類,它的主要作用是抽象出家用電裝置的基本屬性,提供了裝置編號和裝置型別這兩個核心屬性的定義以及對應的訪問方式(透過建構函式初始化屬性,並可以透過成員變數直接訪問)。同時定義了 displayInfo 方法,雖然在基類中該方法預設返回空字串,但它為子類重寫提供了一個統一的介面,用於展示不同裝置的特定資訊,是整個類層次結構中實現多型展示裝置資訊的關鍵設計點。

  2. 各子類(SpeedRegulatorApparatusType、SwitchApparatusType 等)
    屬性與行為擴充套件:
      SpeedRegulatorApparatusType 類:新增了 speedLevelValue 屬性用於表示調速裝置的速度級別,透過 generateOutputVoltage 方法根據速度級別返回相應的輸出電壓值,並重寫了 displayInfo 方法來展示裝置編號和當前速度級別,體現了針對調速裝置特有的功能和資訊展示需求進行的設計,實現了對調速裝置在這個模擬系統中的具體行為建模。

  SwitchApparatusType 類:包含 isSwitchedOn 屬性用於表示開關狀態,提供了 toggleSwitch 方法來切換開關狀態,其 generateOutputVoltage 方法根據開關狀態決定是否輸出輸入電壓,displayInfo 方法展示裝置編號和開關狀態對應的文字描述(“closed” 或 “turned on”),完整地刻畫了開關裝置在系統中的操作和狀態呈現方式。

  ContinuouslyAdjustableApparatusType 類:引入 parameterValueAmount 屬性來表示連續可調裝置的引數值,有 setParameterValue 方法用於設定該引數,generateOutputVoltage 方法根據引數值與輸入電壓計算輸出電壓,displayInfo 方法展示裝置編號和格式化後的引數值,滿足了連續可調裝置在引數設定及相關功能、資訊展示方面的要求。

  IncandescentLightApparatusType 類:具備 brightnessLevelValue 屬性記錄白熾燈的亮度級別,透過 setBrightnessValue 方法根據輸入電壓按照不同的範圍條件設定亮度值,displayInfo 方法展示裝置編號和亮度級別,針對白熾燈根據電壓改變亮度這一特性進行了合理的功能設計。

  FluorescentLightApparatusType 類:同樣有 brightnessLevelValue 屬性,其 setBrightnessValue 方法簡單地根據輸入電壓是否為 0 來設定亮度(非 0 則設為固定值 180),displayInfo 方法展示相應資訊,體現了熒光燈亮度設定相對簡單的特點。

  FanApparatusType 類:包含 speedValue 屬性表示風扇的轉速,setRotationSpeedValue 方法依據輸入電壓在不同的範圍條件下設定轉速,displayInfo 方法展示裝置編號和轉速,實現了對風扇裝置轉速調節及資訊展示的功能模擬。

  共性與差異體現:這些子類都繼承自 HomeElectricalApparatus 類,複用了父類的裝置編號和裝置型別屬性,同時各自按照裝置的實際功能需求新增了獨特的屬性和對應的行為方法,重寫了 displayInfo 方法以展示自身特有的關鍵資訊,既體現了作為家用電器裝置的共性(在整體系統中被統一管理、有通用的基礎屬性等),又突出了不同型別裝置之間的功能差異。

  1. ApparatusComparatorType 類
    功能實現:該類實現了 java.util.Comparator 介面,透過重寫 compare 方法定義了裝置物件之間的比較規則。具體來說,先按照預設的裝置型別順序(透過 typeOrder 陣列定義)對裝置進行排序,如果裝置型別相同,則進一步按照裝置編號(擷取編號字串並轉換為整數後比較)進行排序,以此實現了一種靈活且符合特定業務需求的裝置物件排序機制,方便在需要展示裝置列表時按照一定順序輸出,例如在 Main 類中對處理後的裝置列表進行有序展示就依賴於此比較規則。

  2. CommandHandler 類
    命令處理邏輯:作為命令處理的核心類,它提供了靜態方法 handleCommands,接收儲存裝置物件的對映表(LinkedHashMap<String, HomeElectricalApparatus>)和控制命令列表(LinkedList)作為引數。在方法內部,透過迴圈遍歷控制命令列表,根據命令字串的開頭標識(如 #K、#F、#L 等)來判斷命令型別,然後按照不同的命令格式解析並呼叫相應裝置子類的方法執行具體操作,例如對於開關類裝置的開關切換、調速裝置的速度調節、連續可調裝置的引數設定等操作,實現了將輸入的控制命令轉化為對具體裝置物件操作的功能,是整個系統中實現使用者互動控制裝置的關鍵環節。

  3. VoltageProcessor 類
    電壓處理流程:此類負責模擬電壓在不同型別家用電器裝置之間的傳遞以及對裝置狀態的影響,透過 processVoltage 方法實現相關功能。方法內部首先獲取儲存裝置物件的列表(LinkedList),並設定初始輸入電壓值,然後透過兩次遍歷裝置列表,第一次根據部分裝置(開關類、調速類、連續可調類)對電壓的影響來更新輸入電壓值,第二次根據剩餘裝置(白熾燈、熒光燈、風扇等)根據更新後的電壓值來設定自身的狀態(如亮度、轉速等),完整地模擬了電壓在整個電器系統中的作用過程以及各裝置對電壓的響應情況,是實現裝置狀態根據電壓變化而動態調整的關鍵所在。

2.類圖

3.家居強電電路模擬程式-2
  1.類的設計
1.1整體類結構設計思路
基於題目描述的家居電路模擬需求,設計一套類結構來對各種電路裝置、電路連線情況以及相應的控制與狀態展示進行建模。整體思路是以抽象出的公共特徵為基礎構建基類,然後透過繼承等方式派生出不同型別的具體類,同時考慮不同電路結構(串聯、並聯)也作為類來表示,使得各類之間相互協作,共同完成家居電路的模擬功能。
1.2具體類設計

  1. 電路裝置基類(CircuitDevice)
    屬性:
    deviceId:String型別,用於標識裝置的編號,例如 K1、F3 等,遵循題目中裝置標識的格式要求,透過它可以唯一區分不同的裝置個體。
    deviceType:String型別,儲存裝置的型別識別符號,如 K(開關)、F(分檔調速器)、L(連續調速器)、B(白熾燈)、R(日光燈)、D(吊扇)、A(落地扇)等,方便根據型別進行不同的行為處理。
    方法:
    getDeviceId():返回裝置編號,用於外部獲取裝置的唯一標識。
    getDeviceType():返回裝置型別識別符號,使得其他類可以知曉該裝置所屬型別,進而執行相應的邏輯。
    displayStatus():定義一個抽象方法,用於展示裝置當前的狀態或引數,不同的子類會根據自身裝置特點重寫該方法來返回具體的狀態資訊,符合多型性的設計原則,例如開關展示開關狀態,調速器展示檔位資訊,燈展示亮度,風扇展示轉速等。
  2. 控制裝置類(ControlDevice)
    繼承關係:繼承自 CircuitDevice 類,複用基類的裝置編號和裝置型別屬性,同時擴充套件控制裝置特有的行為和屬性。
    屬性:
    inputPin:int 型別,代表輸入引腳編號,對於所有控制裝置(開關、調速器等),按照題目要求輸入引腳編號固定為 1,但透過屬性定義方便後續可能的擴充套件或靈活配置。
    outputPin:int 型別,代表輸出引腳編號,固定為 2,同樣考慮到可擴充套件性而作為屬性存在。
    currentState:對於開關裝置,用 boolean 型別表示當前開關狀態(true 表示合上,false 表示開啟);對於調速器裝置,可以用 int(分檔調速器的當前檔位)或者 double(連續調速器的當前檔位引數)型別來表示當前的調節狀態,初始狀態按照題目要求都設為 0。
    方法:
    toggleSwitch():對於開關裝置,實現切換開關狀態的功能,內部修改 currentState 屬性的值,實現狀態的改變(currentState =!currentState)。
    adjustSpeed(String operation):針對調速器裝置,接收一個表示操作的字串引數(如 "+" 表示升檔,"-" 表示降檔,對於連續調速器也可以是具體的數值字串用於設定檔位引數),根據不同的裝置型別(分檔調速器或連續調速器)執行相應的速度調節邏輯,更新 currentState 屬性的值,體現了對不同調速器操作的統一介面。
    generateOutputVoltage(double inputVoltage):根據當前裝置的狀態(開關的開合狀態、調速器的檔位等)以及輸入電壓,按照各自裝置的規則(開關狀態決定是否輸出輸入電壓、調速器根據檔位比例計算輸出電壓等)計算並返回輸出電壓值,模擬了控制裝置對電壓的處理邏輯。
  3. 受控裝置類(ControlledDevice)
    繼承關係:同樣繼承自 CircuitDevice 類,利用基類的基礎屬性,並新增受控裝置特有的屬性和行為。
    屬性:
    pin1Voltage:double 型別,記錄裝置第一個引腳的電壓值,用於後續根據引腳間電壓差來確定裝置的工作狀態和相關引數(如亮度、轉速等)。
    pin2Voltage:double 型別,記錄裝置第二個引腳的電壓值,與 pin1Voltage 配合使用。
    resistance:double 型別,儲存裝置的電阻值,按照題目給定的不同裝置電阻(如白熾燈電阻為 10,日光燈電阻為 5 等)進行初始化,用於後續可能涉及到的包含電阻的電路計算(在後續迭代中會用到)。
    方法:
    setPinVoltages(double pin1Voltage, double pin2Voltage):用於設定裝置兩個引腳的電壓值,方便在電路連線和電壓傳遞過程中更新裝置引腳的電壓情況,外部可以透過該方法告知裝置當前的電壓輸入情況。
    calculateStatus():根據兩個引腳間的電壓差以及裝置自身的特性(如白熾燈根據不同電壓差確定亮度,風扇根據電壓差確定轉速等),按照題目給定的規則計算並更新裝置的內部狀態(例如亮度值、轉速值等),是實現受控裝置根據電路電壓情況做出響應的核心方法。
    displayStatus():重寫基類的 displayStatus 方法,按照輸出格式要求展示裝置當前的狀態資訊(如燈的亮度、風扇的轉速等),實現了多型展示受控裝置狀態的功能。
  4. 串聯電路類(SeriesCircuit)
    屬性:
    devices:List 型別,用於儲存構成該串聯電路的所有電路裝置物件,按照從電源端到接地端的順序依次新增,方便後續模擬電壓在串聯電路中的依次傳遞等操作。
    circuitId:String 型別,標識該串聯電路的編號,用於區分不同的串聯電路,遵循題目中串聯電路編號的格式要求。
    方法:
    addDevice(CircuitDevice device):向串聯電路中新增一個電路裝置物件,將其新增到 devices 列表末尾,實現串聯電路裝置的組裝功能,便於構建具體的串聯電路結構。
    simulateVoltageFlow(double inputVoltage):模擬電壓在串聯電路中的流動過程,從輸入電壓開始,按照順序依次呼叫每個電路裝置的 generateOutputVoltage 方法(對於控制裝置)或者 setPinVoltages 方法(對於受控裝置),傳遞電壓並更新各裝置的引腳電壓情況,最終返回經過串聯電路後的輸出電壓,實現了串聯電路中電壓傳遞和對裝置作用的模擬功能。
    displayCircuitStatus():遍歷 devices 列表,呼叫每個裝置的 displayStatus 方法,按照順序輸出串聯電路中所有裝置的狀態資訊,方便展示整個串聯電路中各裝置的狀態情況,符合題目要求的輸出格式和順序。
  5. 並聯電路類(ParallelCircuit)
    繼承關係:繼承自 CircuitDevice 類,將並聯電路也看作是一個獨立的電路裝置,這樣可以方便地將其融入到更復雜的電路結構(如多個並聯電路串聯等情況,在後續迭代中會涉及)中進行統一管理和處理。
    屬性:
    seriesCircuits:List 型別,儲存構成該並聯電路的所有串聯電路物件,體現了並聯電路由多個串聯電路組成的結構特點。
    circuitId:String 型別,標識該並聯電路的編號,與串聯電路編號類似,用於區分不同的並聯電路。
    方法:
    addSeriesCircuit(SeriesCircuit seriesCircuit):將一個串聯電路物件新增到並聯電路中,新增到 seriesCircuits 列表內,實現構建並聯電路的功能,透過新增多個串聯電路來組成具體的並聯電路結構。
    simulateVoltageFlow(double inputVoltage):模擬電壓在並聯電路中的流動情況,由於並聯電路各支路電壓相等,對每個包含的串聯電路都呼叫 simulateVoltageFlow 方法並傳入相同的輸入電壓,然後綜合各支路的情況(例如在後續迭代考慮電流等引數時可以進行相應計算和處理),返回經過並聯電路後的輸出電壓,實現了並聯電路中電壓傳遞的模擬以及對各串聯支路的統一處理
    功能。
    displayCircuitStatus():遍歷 seriesCircuits 列表,依次呼叫每個串聯電路的 displayCircuitStatus 方法,按照順序輸出並聯電路中所有串聯電路包含的裝置狀態資訊,實現了展示整個並聯電路及其內部各串聯電路中所有裝置狀態的功能,滿足題目對輸出格式和順序的要求。
    1.3類之間的協作關係
    在構建整個家居電路模擬系統時,首先建立各種具體的控制裝置(開關、調速器等)和受控裝置(燈、風扇等)物件,它們都是 CircuitDevice 的子類,各自初始化相應的屬性,如裝置編號、型別以及初始狀態等。
    然後根據輸入的串聯電路資訊,建立 SeriesCircuit 物件,透過 addDevice 方法將對應的電路裝置新增到串聯電路中,構建出具體的串聯電路結構;對於並聯電路資訊,建立 ParallelCircuit 物件,並透過 addSeriesCircuit 方法將相關的串聯電路新增進去,形成並聯電路結構。
    在類比電路執行時,從電源(VCC,給定電壓 220V)開始,對於串聯電路,呼叫 SeriesCircuit 的 simulateVoltageFlow 方法,讓電壓在串聯電路中依次傳遞並作用於各裝置,裝置根據自身邏輯(控制裝置處理電壓輸出,受控裝置根據電壓差計算狀態)進行響應;對於並聯電路,呼叫 ParallelCircuit 的 simulateVoltageFlow 方法,使得電壓在各並聯支路(串聯電路)中傳遞並處理,最終完成整個電路的電壓傳遞和裝置狀態更新。
    最後,透過呼叫各個電路(串聯電路或並聯電路)的 displayCircuitStatus 方法,按照題目要求的順序輸出所有裝置的狀態資訊,展示整個家居電路的模擬結果。

2.類圖

踩坑心得

  針對第四次大作業中的答題判斷4的踩坑分析:
  

  1. 試卷引用檢查不完善
    在程式碼中,雖然有部分地方對試卷是否存在進行了檢查,例如在以下程式碼片段中:
    for (Answer answer : answerList) {
    int key = answer.getPaperID();
    if (!examinationMap.containsKey(key)) {
    System.out.println("The test paper qusid does not exist");
    continue;
    }
    // 後續其他邏輯處理
    }
    這裡會檢查試卷編號對應的試卷是否存在於 examinationMap 中,但檢查相對比較簡單,只是輸出提示資訊後跳過當前答案的後續處理。可能在後續更復雜的邏輯中,對於試卷引用無效的情況沒有全面地阻斷相關的錯誤邏輯繼續執行,導致出現不符合預期的結果。例如,如果在後續基於試卷資訊進行一些計算或者展示操作時,假設試卷不存在卻依然嘗試去獲取試卷中的題目等相關資料,就可能引發異常或者輸出錯誤的結果。

  2. 缺乏統一的錯誤處理機制
    對於試卷引用無效這種錯誤情況,只是簡單地輸出提示語句,沒有采用一種統一的、規範的錯誤處理方式,這可能導致在整個程式執行過程中,一旦出現試卷引用無效的情況,後續邏輯執行的穩定性和正確性無法得到保障,進而無法透過相關測試點的驗證。

  3. 與其他功能邏輯的耦合問題
    在處理學生答案、計算成績等相關邏輯中,與試卷引用的判斷邏輯交織在一起,使得程式碼的可讀性和維護性變差。當出現試卷引用無效的情況時,很難清晰地追蹤哪些邏輯受到了影響以及是否所有相關的處理都正確地進行了錯誤處理或者回退操作,容易出現遺漏的情況,影響了程式在面對這種特定錯誤場景時的健壯性。

  4. 依賴順序假設的處理邏輯
    程式碼中的一些邏輯可能隱含地假設了輸入資料的順序,就比如在處理學生答案、試卷資訊以及學生資訊的過程中,可能想要按照某種特定順序先輸入試卷相關內容,再輸入學生相關內容,最後輸入答案相關內容等。但對於多試卷多學生亂序輸入的情況,這種基於順序的處理邏輯就會出現問題。就比如:
    for (Answer answer : answerList) {
    int key = answer.getPaperID();
    // 查詢對應的學生資訊等邏輯
    Pupil pupil = new Pupil(-1, ""); int symbol = 0; for (Pupil stu : pupilList) { if (answer.getPupilID() == stu.getPupilID()) { symbol = 1; pupil = stu; break; } } // 後續基於試卷、學生、答案的處理邏輯 }
    如果學生資訊和答案資訊的輸入順序不符合預期,可能會導致在查詢對應學生資訊時出現找不到的情況(即使學生實際存在,只是因為輸入順序問題還未被正確新增到 pupilList 中),進而影響後續整個答題結果的處理和展示邏輯,導致輸出不符合要求,無法透過測試。

  5. 資料關聯和匹配邏輯的脆弱性
    在處理多個試卷、多個學生以及他們之間的關聯(透過試卷編號、學生編號等建立聯絡)時,程式碼中對於資料的匹配和關聯邏輯不夠健壯。當出現亂序輸入時,難以準確地將學生的答案對應到正確的試卷以及正確的學生個體上,可能出現張冠李戴的情況,使得最終計算成績、展示結果等功能出現錯誤。例如,在根據答案中的試卷編號查詢試卷資訊以及根據學生編號查詢學生資訊時,沒有充分考慮亂序輸入帶來的影響,沒有足夠的機制來確保資料之間的準確匹配和關聯,從而影響了程式對這種複雜輸入場景的應對能力。

踩坑心得總結

  1. 輸入驗證與錯誤處理要全面且規範
    對於程式接收的各種輸入資料,無論是試卷資訊、學生資訊還是答案資訊等,都要進行全面細緻的驗證,不僅僅是簡單地檢查格式是否正確,還要對資料之間的關聯性(如試卷引用是否有效、學生與答案是否能準確對應等)進行嚴格校驗。同時,要建立統一規範的錯誤處理機制,透過丟擲合適的異常等方式,讓程式在出現錯誤時能夠明確告知呼叫者具體的錯誤情況,方便進行針對性的處理,而不是簡單地輸出提示資訊後任由程式繼續執行,可能導致更復雜難以排查的錯誤出現。
  2. 避免順序依賴
    在設計程式邏輯時,要儘量避免依賴輸入資料的特定順序來保證功能的正確性。程式碼的邏輯應該基於資料本身的關聯性和內在的業務規則來編寫,而不是假設使用者會按照某種固定順序輸入資料。如果確實需要一定的順序,可以在程式開始處對輸入資料進行整理排序,或者透過更清晰的標識和匹配機制來確保無論輸入順序如何,都能正確地處理資料之間的關係,提高程式對不同輸入順序情況的適應性和健壯性。

不同功能模組(如試卷管理、學生管理、答題結果處理等)之間的邏輯應該儘量解耦,避免相互之間高度依賴和複雜的交織,這樣當出現某一型別的錯誤(如試卷引用無效)時,能夠清晰地定位到受影響的程式碼範圍,方便進行針對性的修改和完善。同時,提高程式碼的可讀性也很重要,透過合理的命名、清晰的程式碼結構以及適當的註釋等方式,讓程式碼邏輯易於理解,便於後續排查問題以及對程式進行維護和最佳化,以應對各種複雜的測試場景和實際使用情況。
4. 考慮複雜場景並提前設計應對機制
在開發程式時,不能僅僅滿足於對常規輸入情況的功能實現,要充分考慮到可能出現的各種複雜場景,像本題中的亂序輸入情況。在設計階段就應該提前規劃好相應的應對機制,例如設計合適的資料結構和演算法來處理亂序資料、增加額外的標識或狀態來輔助資料的準確匹配等,這樣可以避免在後期測試或者實際應用中才發現程式無法應對這些複雜情況,減少返工和修改程式碼的成本,提升程式的整體質量和實用性。
總之,透過這次遇到的測試點未透過的情況,深刻認識到在編寫程式碼時要從多方面考慮程式的健壯性、對不同輸入場景的適應性以及程式碼的可維護性等因素,避免踩到類似的 “坑”,確保程式能夠穩定可靠地執行並滿足各種需求。

針對第五次大作業家電程式-1的踩坑分析

在 IncandescentLightApparatusType 類中,用於設定白熾燈亮度值的 setBrightnessValue 方法裡,雖然對幾個特殊電壓值(如 0 - 9、10、220)對應的亮度做了明確處理,但對於其他中間電壓值的亮度計算邏輯可能不夠準確。特別是在模擬分檔情況時,如果期望是按照一定的規則分檔來確定亮度,當前程式碼只是簡單地透過線性比例計算中間值亮度(基於 (entryDianYa - 9) / (220.0 - 10) 這個比例來計算),可能沒有考慮到實際分檔的具體細節要求,例如分檔邊界情況、舍入規則等與預期分檔邏輯不一致,導致最終計算出的亮度值不符合正確答案要求。
例如程式碼中的這部分邏輯:
if (entryDianYa >= minRange && entryDianYa <= maxRange) {
brightnessLevelValue = 0;
} else if (entryDianYa == 10) {
brightnessLevelValue = specialValueAtTen;
} else if (entryDianYa == 220) {
brightnessLevelValue = specialValueAtTwoTwenty;
} else if (entryDianYa > 9 && entryDianYa < 220) {
double ratio = (entryDianYa - 9) / (220.0 - 10);
brightnessLevelValue = (int)(baseValueForIntermediate + ratio * rangeForIntermediate);
}
對於分檔情況,可能需要更精細地劃分不同電壓區間對應不同的固定亮度檔位,而不是簡單的線性比例計算。

與其他裝置互動時的電壓傳遞影響
整個程式透過 VoltageProcessor 類來模擬電壓在各個裝置間的傳遞,對於分檔白熾燈來說,它接收到的輸入電壓是經過前面控制裝置(如開關、調速器等)處理後的電壓。如果在前面控制裝置對電壓的處理邏輯(例如開關的開合狀態、調速器的檔位調節等)存在錯誤或者不符合預期的情況,那麼傳遞到白熾燈的電壓就不正確,進而導致根據該電壓計算出的亮度值也是錯誤的。
比如在 VoltageProcessor 類中的這段電壓傳遞程式碼:

for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "K":
entryDianYa = ((SwitchApparatusType) e).generateOutputVoltage(entryDianYa);
break;
case "F":
entryDianYa = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(entryDianYa);
break;
case "L":
entryDianYa = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(entryDianYa);
break;
}
}
如果開關沒有正確地控制電壓通斷,或者調速器輸出的電壓不符合分檔白熾燈預期的輸入電壓範圍及分檔邏輯,都會影響最終白熾燈亮度計算的準確性。

  1. 程式碼結構與功能模組劃分不清晰:整個程式碼雖然按照裝置型別、命令處理、電壓處理等功能劃分了不同的類,但在類內部的方法職責劃分可能不夠清晰。例如在 VoltageProcessor 類中,既處理了電壓在裝置間的傳遞邏輯,又包含了根據電壓設定不同裝置狀態的邏輯,功能較為複雜且耦合度較高。如果後續需要對電壓傳遞邏輯或者裝置狀態設定邏輯進行單獨修改或擴充套件,可能會影響到類中其他相關邏輯,增加程式碼出錯的風險。應該進一步細化類內部方法的職責,降低功能模組之間的耦合度,提高程式碼的可維護性和擴充套件性。
    比如說可以把 VoltageProcessor 類中原本混合在一起的電壓傳遞邏輯和根據電壓設定裝置狀態的邏輯拆分開,分別封裝到不同的方法中,使每個方法專注於一個明確的功能職責。這樣一來,當後續需要對其中某一個功能進行修改或擴充套件時,能夠更方便地定位和操作相應程式碼,而不會影響到另一個功能相關的邏輯,降低出錯的風險。
    class VoltageProcessor {
// 單獨的方法用於處理電壓在裝置間的傳遞邏輯
public static double transferVoltageAmongApparatus(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap) {
    double entryDianYa = 220;
    LinkedList<HomeElectricalApparatus> apparatusList = new LinkedList<>(apparatusMap.values());

    // 遍歷裝置列表,根據裝置型別模擬電壓的傳遞
    for (HomeElectricalApparatus e : apparatusList) {
        switch (e.apparatusType) {
            case "K":
                entryDianYa = ((SwitchApparatusType) e).generateOutputVoltage(entryDianYa);
                break;
            case "F":
                entryDianYa = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(entryDianYa);
                break;
            case "L":
                entryDianYa = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(entryDianYa);
                break;
        }
    }

    return entryDianYa;
}

// 單獨的方法用於根據傳遞後的電壓設定不同裝置的狀態
public static LinkedList<HomeElectricalApparatus> setApparatusStatesBasedOnVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double finalVoltage) {
    LinkedList<HomeElectricalApparatus> apparatusList = new LinkedList<>(apparatusMap.values());

    // 再次遍歷裝置列表,根據裝置型別和輸入電壓設定裝置的狀態
    for (HomeElectricalApparatus e : apparatusList) {
        switch (e.apparatusType) {
            case "B":
                ((IncandescentLightApparatusType) e).setBrightnessValue(finalVoltage);
                break;
            case "R":
                ((FluorescentLightApparatusType) e).setBrightnessValue(finalVoltage);
                break;
            case "D":
                ((FanApparatusType) e).setRotationSpeedValue(finalVoltage);
                break;
        }
    }

    return apparatusList;
}
public static LinkedList<HomeElectricalApparatus> processVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap) {
    double finalVoltage = transferVoltageAmongApparatus(apparatusMap);
    return setApparatusStatesBasedOnVoltage(apparatusMap, finalVoltage);
}

}
踩坑心得總結
編寫程式碼過程中要時刻關注程式碼的可維護性和擴充套件性,精心設計程式碼結構,合理劃分功能模組,明確每個方法的職責,降低模組之間的耦合度,使程式碼易於理解、修改和擴充套件,這樣在面對不斷變化的需求和功能迭代時,才能更高效地進行程式碼維護和開發工作。
總之,透過完成這個題目,從多個方面積累了寶貴的經驗教訓,對後續處理類似複雜的程式設計任務在功能實現、問題排查以及程式碼質量把控等方面都有很好的指導作用,提醒自己要更加嚴謹、全面地思考和編寫程式碼。
針對第六次大作業的家居電路程式-2的踩坑分析

連線資訊解析複雜:輸入的連線資訊格式較為複雜,使用正規表示式解析的時候出錯 在處理 引腳組合以及不同引腳之間的分隔時,正規表示式的模式匹配不準確,導致引腳提取錯誤,影響後續對裝置連線關係的構建和電壓傳遞計算。

並聯電路連線邏輯混淆:對於並聯電路的連線邏輯理解不夠清晰,尤其是在處理多個串聯電路組成並聯電路時,如何正確地合併引腳連線關係、確定電壓在並聯分支中的分配等方面容易出現錯誤。

將過多的裝置連線處理邏輯和電壓計算邏輯都放在一個類中,當需要對某個功能進行修改或擴充套件時,會影響到其他相關功能,增加程式碼出錯的風險,並且不利於程式碼的維護和閱讀。

踩坑心得總結
1.
在開始編寫程式碼之前,要對對家居電路模擬的業務規則進行深入細緻的分析和理解。包括各種裝置的特性、工作原理、連線方式、狀態轉換條件以及輸入輸出格式等。只有對這些規則有清晰的把握,才能在程式碼實現過程中準確地翻譯業務需求,避免因對業務理解偏差而導致的各種錯誤。
2.
根據題目特點,選擇合適的資料結構來儲存裝置資訊、連線關係等資料。例如,可以使用圖資料結構來表示電路中裝置的連線關係,以便更方便地進行電壓傳遞計算和裝置遍歷。
3.
編寫程式碼過程中要遵循嚴謹的程式設計規範,注重程式碼的可讀性和可維護性。對於複雜的邏輯部分,新增詳細的註釋,方便自己和他人理解程式碼意圖。同時,要進行全面的測試,包括單元測試、整合測試和邊界測試等。針對不同型別的裝置、各種連線情況以及控制命令組合,編寫大量的測試用例,儘可能覆蓋所有可能的情況,及時發現並修復程式碼中的漏洞。例如,測試開關在不同初始狀態下切換命令的執行結果,以及不同電壓輸入下受控裝置的狀態變化是否符合預期等。

改進建議

1.針對答題程式-4的改進

目前程式碼雖然按照不同概念劃分了多個類,如 Matter 及其子類用於表示題目,Examination 類處理試卷相關資訊等,但部分類職責不夠清晰明確,存在功能重疊的情況。
ScannerParser 類承擔了過多不同型別輸入的解析工作,各種解析方法堆積在一起,程式碼顯得臃腫且複雜,一旦某個輸入格式發生變化或者需要新增一種輸入格式,整個類都可能需要大面積修改,可維護性較差。
拆分 ScannerParser 類,按照輸入型別建立多個獨立的解析器類,例如 QuestionParser 負責解析題目相關輸入(包含普通題、多選題、填空題等),TestPaperParser 專門解析試卷資訊輸入,StudentAnswerParser 和 StudentInfoParser 分別處理學生答案和學生資訊的輸入解析。這樣每個類職責單一,程式碼的可讀性和可維護性都會大大提高,也方便針對不同輸入型別進行單獨的功能擴充套件和錯誤處理最佳化。

在 Main 類中有一段程式碼用於驗證試卷總分是否為 100 分,目前的實現方式是遍歷 examinationMap 中的每個試卷物件,呼叫 calculateFullPoint 方法計算總分並與 100 進行比較,如果不相等則輸出提示資訊。這種方式功能上可以實現驗證,但程式碼放在 Main 類的主流程中,使得主流程的邏輯不夠清晰,而且驗證邏輯相對獨立,與其他業務邏輯(如學生答案處理、成績計算等)關聯性不強,混合在一起不利於程式碼的維護和擴充套件。
將試卷總分驗證邏輯抽取到一個獨立的方法中,比如在專門的資料驗證類中建立一個 validateExaminationTotalScore 方法,接收 examinationMap 作為引數,在該方法內部完成對所有試卷總分的驗證,並輸出相應的提示資訊。這樣程式碼結構更加清晰,主流程專注於核心的業務邏輯(如輸入解析後的資料處理和結果輸出等),而資料驗證作為一個獨立的功能模組,方便單獨進行測試和維護。

目前 printResults 方法的程式碼結構是基於現有的題目型別(多選題、填空題等)和輸出格式要求編寫的,如果後續需要增加新的題目型別或者改變輸出格式規則(比如增加更多的答題狀態標識、調整成績的顯示格式等),現有的程式碼可能需要進行較大幅度的修改,可擴充套件性不足。
考慮採用更靈活的設計方式來應對可能的變化,例如可以定義一個介面(如 QuestionResultPrinter),不同的題目型別實現這個介面並提供各自的答題結果輸出方法,在 printResults 方法中根據題目型別呼叫相應的實現類方法來輸出答題結果,這樣當新增題目型別時,只需建立新的實現類遵循介面規範實現輸出邏輯即可,無需大面積修改現有的 printResults 方法程式碼,提高程式碼的可擴充套件性。

遵循更規範、表意清晰的變數命名原則,使用有意義的英文單詞或片語來命名變數,而不是拼音和英文組合 雜亂無章的命名。

2.針對家居電器程式-1的改進建議

整體上我按照不同的電器裝置型別和功能劃分了多個類,如各類電器裝置類(SpeedRegulatorApparatusType、SwitchApparatusType 等)以及負責命令處理、電壓處理的類,這種劃分有一定合理性,但部分類的職責可以更純粹、細化。
例如,VoltageProcessor 類中既包含了電壓在裝置間傳遞的邏輯,又有根據最終電壓設定各裝置狀態的邏輯,功能較為複雜,不利於程式碼的維護和擴充套件,如果後續需要單獨修改電壓傳遞規則或者裝置狀態設定的邏輯,可能會影響到類中的其他部分。
各個電器裝置類中,有些屬性的定義和初始化方式稍顯隨意,比如在 IncandescentLightApparatusType 類中,亮度計算相關的多個常量(minRange、maxRange 等)直接在 setBrightnessValue 方法中定義,若後續這些常量需要根據不同場景調整,在多個方法中查詢和修改會比較麻煩,而且程式碼的複用性也較差。
對於 VoltageProcessor 類,可將電壓傳遞和裝置狀態設定這兩個主要功能拆分成兩個獨立的方法,甚至可以考慮進一步抽象出專門的電壓傳遞類和裝置狀態更新類,使每個類專注於一項核心職責,降低耦合度,提高可維護性和擴充套件性。例如:

class VoltageTransfer {
public static double transferVoltage(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double initialVoltage) {
// 實現電壓在裝置間傳遞的邏輯,返回最終傳遞後的電壓
double currentVoltage = initialVoltage;
LinkedList apparatusList = new LinkedList<>(apparatusMap.values());
for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "K":
currentVoltage = ((SwitchApparatusType) e).generateOutputVoltage(currentVoltage);
break;
case "F":
currentVoltage = ((SpeedRegulatorApparatusType) e).generateOutputVoltage(currentVoltage);
break;
case "L":
currentVoltage = ((ContinuouslyAdjustableApparatusType) e).generateOutputVoltage(currentVoltage);
break;
}
}
return currentVoltage;
}
}

class ApparatusStateSetter {
public static void setApparatusStates(LinkedHashMap<String, HomeElectricalApparatus> apparatusMap, double finalVoltage) {
LinkedList apparatusList = new LinkedList<>(apparatusMap.values());
for (HomeElectricalApparatus e : apparatusList) {
switch (e.apparatusType) {
case "B":
((IncandescentLightApparatusType) e).setBrightnessValue(finalVoltage);
break;
case "R":
((FluorescentLightApparatusType) e).setBrightnessValue(finalVoltage);
break;
case "D":
((FanApparatusType) e).setRotationSpeedValue(finalVoltage);
break;
}
}
}
}

目前 CommandHandler 類中對命令的解析處理邏輯覆蓋的情況不夠全面,只考慮了基本的幾種命令格式(如開關切換、調速器加檔 / 減檔、連續調速器設定引數),對於一些可能的錯誤輸入情況或者擴充套件的命令格式沒有進行很好的處理。例如,如果輸入的命令中調速器的運算子(+、-)位置不對、連續調速器設定引數的格式不符合要求(如引數不是合法的數字等),程式碼可能會出現異常或者得到錯誤的處理結果。
對於命令中裝置編號的驗證不夠嚴謹,只是簡單判斷在 apparatusMap 中是否存在該編號對應的裝置,如果存在就執行相應操作,沒有進一步驗證裝置編號與命令對應的裝置型別是否一致,可能導致邏輯錯誤,比如用開關的編號去執行調速器的操作命令等情況。

完善命令格式的校驗邏輯,針對每種命令型別(#K、#F、#L 等)詳細分析可能出現的錯誤格式,增加更多的條件判斷來確保輸入命令的合法性。例如,對於 #F 命令,可以進一步判斷 +、- 運算子後面是否還有其他多餘字元,對於 #L 命令嚴格驗證引數是否是符合要求的數值(可以使用正規表示式或者 try-catch 塊結合 Double.parseDouble 來判斷是否能正確轉換為數字)等。
在根據裝置編號獲取裝置物件並執行操作前,新增裝置型別驗證邏輯,確保命令對應的裝置型別與實際從 apparatusMap 中獲取的裝置型別一致。例如在處理 #F 命令時:

if (command.startsWith("#F")) {
String fCommand = command.substring(1, command.length());
int index1 = fCommand.indexOf("F");
int index2 = fCommand.indexOf("+");
int index3 = fCommand.indexOf("-");
if (index2 > 0) {
String f1 = fCommand.substring(index1, index2);
if (apparatusMap.containsKey(f1)) {
HomeElectricalApparatus apparatus = apparatusMap.get(f1);
if (apparatus instanceof SpeedRegulatorApparatusType) {
((SpeedRegulatorApparatusType) apparatus).speedLevelValue++;
} else {
System.out.println("命令對應的裝置型別不符,無法執行操作");
}
}
} else if (index3 > 0) {
String f2 = fCommand.substring(index1, index3);
if (apparatusMap.containsKey(f2)) {
HomeElectricalApparatus apparatus = apparatusMap.get(f2);
if (apparatus instanceof SpeedRegulatorApparatusType) {
((SpeedRegulatorApparatusType) apparatus).speedLevelValue--;
} else {
System.out.println("命令對應的裝置型別不符,無法執行操作");
}
}
} else {
System.out.println("Wrong Format");
}
}

還有就是要提供程式碼的可讀性和可維護性。

3.針對家居電器程式-2的改進建議
這個題目,我仍在探索中,目前無法給出好的改進建議。不過,我認為需要注意以下一些事項:

電路裝置類(基礎類)

  需定義用於標識裝置的屬性,比如裝置識別符號(如 K、F、L 等)和裝置編號,以便區分不同的具體裝置例項。
考慮新增引腳相關屬性,例如可以用一個資料結構(如陣列或者 Map)來儲存不同引腳對應的連線情況或者電位值等資訊,方便後續電路連線和電壓計算時使用。
由於不同裝置在電路中有不同狀態(如開關的開 / 合狀態、調速器的檔位等),可定義一個通用的狀態屬性,根據具體裝置子類再去細化其含義和取值範圍。

  設計獲取裝置識別符號、編號以及引腳資訊等的訪問器方法(getter),方便在其他類中獲取這些基礎資訊進行操作。
可以建立一個抽象的方法用於計算裝置的輸出電位,因為不同型別的裝置(控制裝置、受控裝置等)計算輸出電位的邏輯不同,在具體子類中去實現該方法的具體邏輯。

  根據具體受控裝置(燈、風扇等)的特點,新增對應屬性。例如對於燈裝置,可以新增表示亮度的屬性;對於風扇裝置,新增表示轉速的屬性等,並且這些屬性的資料型別要按照題目要求(如亮度、轉速等用 double 型別儲存用於中間計算)來定義。
由於不同的受控裝置有不同的工作電壓區間、對應狀態變化等情況,可新增相應屬性來記錄這些特定的引數資訊,便於後續在狀態計算方法中使用。

  重寫父類中計算輸出電位的抽象方法,按照不同受控裝置(如白熾燈、日光燈、吊扇、落地扇等各自的電壓 - 亮度 / 轉速對應關係)來實現具體的計算邏輯,確保輸出電位的計算符合題目給定的規則(如比例關係、區間對應關係等)。
設計方法用於根據輸入電位更新裝置的狀態(如亮度、轉速等),這個方法會在電路電壓傳遞和計算過程中被呼叫,以實時反映裝置狀態的變化。

  針對不同控制裝置(開關、分檔調速器、連續調速器)的特性,新增專屬屬性。例如開關新增表示開關狀態(0 或 1)的屬性;分檔調速器新增表示當前檔位的屬性;連續調速器新增表示檔位引數(範圍在 [0.00 - 1.00])的屬性等,並且注意屬性的初始值設定要符合題目要求(初始狀態 / 檔位為 0)。

  同樣重寫計算輸出電位的抽象方法,按照開關、分檔調速器、連續調速器各自的輸出電位規則(如開關的狀態決定輸出電位是否等於輸入電位、分檔調速器根據檔位輸出相應比例的輸入電壓、連續調速器按檔位引數計算輸出電壓等)來編寫具體邏輯。
對於開關裝置,建立切換開關狀態的方法(實現狀態的取反操作);對於分檔調速器,建立增加檔位和降低檔位的方法;對於連續調速器,建立設定檔位引數的方法,這些方法要遵循題目給定的操作格式和規則,方便在處理控制裝置調節資訊時呼叫。

  需要有一個資料結構(如列表或者陣列)來儲存串聯電路中包含的各個電路裝置物件,以便後續遍歷這些裝置進行電壓傳遞和電路相關計算。
可以新增表示電路編號的屬性,用於唯一標識不同的串聯電路,方便在輸入資訊處理以及後續的電路連線、輸出等操作中進行區分。

  設計方法用於向串聯電路中新增電路裝置,確保裝置按照從電源到接地的順序依次新增(遵循輸入資訊的順序要求),同時在新增過程中可以進行一些合法性校驗(如不考慮調速器串聯到其他調速器的情況等約束條件)。
  建立方法用於計算整個串聯電路的總電阻,根據串聯電路中各個裝置的電阻(題目中已給定不同裝置的電阻值)進行累加計算,該方法在後續涉及電流計算(後續迭代需求)等情況時會用到。
實現方法來模擬電壓在串聯電路中的傳遞過程,按照裝置在電路中的順序,依次呼叫各個裝置的計算輸出電位方法,將上一個裝置的輸出作為下一個裝置的輸入,最終得到串聯電路的輸出電位,傳遞給後續連線的電路或者接地等情況。

  定義一個資料結構(如列表)來儲存其所包含的串聯電路物件,體現並聯電路由多條串聯電路組成的結構特點。
同樣新增表示電路編號的屬性用於唯一標識,便於在輸入處理、電路連線以及輸出環節進行區分和操作。

  設計方法用於向並聯電路中新增串聯電路,新增時要遵循題目給定的約束條件(如本次迭代不考慮並聯電路中包含並聯電路的情況等)進行合法性校驗,保證新增的串聯電路符合要求。
實現方法來計算並聯電路的總電阻,根據並聯電路電阻計算公式(1/R總 = 1/R1 + 1/R2 +... + 1/Rn,其中 R1、R2 等為各串聯電路的電阻),透過呼叫所包含串聯電路的總電阻計算方法來得到並聯電路的總電阻,該屬性在後續涉及電流計算等場景會用到。
建立方法模擬電壓在並聯電路中的傳遞情況,由於並聯電路各支路兩端電壓相等,需要根據各串聯電路的電阻以及總輸入電壓(電源電壓等情況),按照並聯電路電流分配等原理,計算各串聯電路的輸入電壓,再呼叫各串聯電路的電壓傳遞方法來完成整個並聯電路的電壓傳遞過程,最終得到並聯電路的輸出電位並傳遞給後續電路。

  對於輸入的裝置標識(如 K、F、L 等)和裝置編號組合,要嚴格按照格式要求進行校驗,確保輸入的合法性,例如裝置編號必須是數字且符合相應的編號規則(題目中未明確詳細編號規則,但要保證能正確區分不同裝置個體),對於不符合格式的輸入要給出明確的錯誤提示資訊(便於使用者知道具體哪裡輸入有誤)。
針對引腳格式(裝置標識 - 引腳編號)也要進行細緻校驗,確認引腳編號的取值範圍符合預期(如控制裝置引腳編號為 1、2,受控裝置引腳編號也為 1、2 等),同時要保證引腳對應的裝置標識是已定義過的合法裝置,避免出現不存在的裝置引腳輸入情況。

  根據解析後的裝置資訊,建立對應的裝置物件(呼叫相應裝置類的建構函式),並將其儲存到合適的資料結構中(如 Map,可以用裝置標識 + 編號作為鍵,裝置物件作為值,方便後續根據輸入的操作資訊快速查詢對應的裝置進行處理)。

  對於用 [] 括起來的連線資訊,要按照格式要求檢查引腳之間用空格分隔是否正確,同時驗證每個引腳的格式是否符合前面提到的裝置引腳格式要求,若格式有誤,輸出相應錯誤提示。
處理連線資訊時,要遵循題目給定的約束條件,例如不考慮調速器串聯到其他調速器的情況,要在解析過程中進行判斷,如果出現不符合約束的連線情況,進行相應的錯誤處理或者提示。

  根據解析後的連線資訊,將對應的裝置引腳進行連線操作,在程式碼中體現為更新相關裝置物件的引腳連線屬性(例如在裝置類中定義的引腳連線相關的資料結構裡記錄與之相連的其他引腳資訊等),以便後續在電路計算和電壓傳遞過程中能準確獲取連線關係進行相應操作。

  針對不同型別控制裝置(開關、分檔調速器、連續調速器)的調節資訊格式,要嚴格進行格式校驗。例如開關調節資訊必須是 #K + 裝置編號 的格式,分檔調速器調節資訊要符合 #F + 裝置編號 + "+" 或 "-" 的格式,連續調速器調節資訊要滿足 #L + 裝置編號 + ":" + 數值 的格式,對於不符合的輸入及時輸出錯誤提示資訊告知使用者格式錯誤位置。
對於連續調速器調節資訊中的數值部分,要驗證其是否是合法的 double 型別數值,並且範圍在 [0.00 - 1.00] 之間(含兩位小數),不符合要求的數值輸入要進行相應處理(如提示錯誤等)。

  解析出控制裝置調節資訊對應的裝置物件後(透過前面儲存裝置物件的資料結構查詢),按照不同的調節操作型別(切換開關、調速器加檔 / 減檔、設定連續調速器檔位引數等),呼叫對應裝置物件的相應方法(如開關的切換開關狀態方法、調速器的檔位調整方法等)來執行具體的調節操作,確保操作的正確性和符合題目規則。

  對於串聯電路資訊(格式為 #T + 電路編號 + ":" + 連線資訊 + " " + 連線資訊 +... + " " + 連線資訊),要校驗電路編號的唯一性(不同的串聯電路資訊編號不同),檢查連線資訊的格式和順序是否符合要求(從電源端到接地端順序、每個連線資訊的格式正確等),不符合格式的要給出錯誤提示。
對於並聯電路資訊(格式為 #M + 電路編號 + ":" + "[" + 串聯電路資訊 + " " +.... + " " + 串聯電路資訊 + "]"),同樣要驗證電路編號唯一性,檢查所包含的串聯電路資訊是否都已在之前輸入(遵循並聯資訊所包含的串聯電路資訊都在並聯資訊之前輸入的約束條件),以及整個格式是否正確,若有問題及時提示錯誤。

  根據解析後的串聯電路資訊,建立串聯電路物件,將對應的連線資訊中的裝置新增到串聯電路物件中(呼叫串聯電路類的新增裝置方法),構建出完整的串聯電路結構,並儲存到合適的資料結構中(如列表或者 Map,方便後續處理並聯電路以及整個電路的連線和計算等操作)。
對於並聯電路資訊,建立並聯電路物件,將解析出的串聯電路物件新增到並聯電路物件中(呼叫並聯電路類的新增串聯電路方法),形成完整的並聯電路結構,同樣儲存好以便後續進行整個電路的組裝和計算等操作,並且在組裝過程中要遵循題目給定的各種約束條件(如不考慮多個並聯電路串聯、不考慮並聯電路中包含並聯電路等情況)進行合法性校驗,避免出現不符合要求的電路結構。

  儘量將不同功能的程式碼劃分到不同的類和方法中,例如輸入解析相關的邏輯放在專門的輸入處理類或方法中,電路計算相關功能封裝在電路相關的類方法裡,輸出相關操作獨立成輸出處理模組等,使得程式碼結構清晰,各部分職責明確,便於後續的維護、擴充套件以及除錯。

  不同類之間透過合理定義介面來進行互動,例如電路裝置類可以定義一些通用的介面方法供其子類實現,串聯電路類與並聯電路類之間透過介面規範彼此呼叫的方法(如獲取電阻、傳遞電壓等方法),這樣可以降低類之間的耦合度,提高程式碼的可擴充套件性和可維護性,方便在後續迭代(如電路結構變化、增加新電路元件等情況)時進行程式碼的修改和功能擴充套件。

總結

透過這三次大作業,我學到了透過繼承來擴充套件類功能,像 ManySelectMatter 和 TianKongMatter 類繼承自 Matter 類,它們複用了父類的基本屬性和方法,同時又可以根據自身代表的不同題型(多選題、填空題)來進行特定的處理,體現了繼承在程式碼複用和業務邏輯細分方面的優勢。
在 WorkoutOutput 類的 printResults 方法中,透過判斷 question 例項屬於不同的子類(ManySelectMatter、TianKongMatter 等)來執行不同的邏輯,展示了多型性的應用,即根據物件的實際型別來決定呼叫哪個類中重寫的方法,使得程式碼可以靈活應對多種題型的評判需求。
以及將整個程式劃分為不同功能模組和層次的重要性與優勢。
例如,將輸入處理、電路計算、裝置狀態更新以及輸出處理等功能分別封裝在獨立的類或方法中,形成清晰的功能模組劃分。這種模組化設計使得每個部分的功能職責明確,程式碼結構更加清晰易讀,方便開發人員進行獨立開發、測試與維護,降低了程式碼的複雜性和耦合度。當需要對某個功能進行修改或擴充套件時,只需關注對應的模組,而不會對其他無關部分造成影響,極大地提高了程式碼的可維護性和可擴充套件性。
也體會到在系統架構設計中,各模組之間透過合理定義介面進行互動的必要性。比如電路裝置類定義通用的介面方法供其子類實現,串聯電路類與並聯電路類之間透過規範的介面來實現相互呼叫(如獲取電阻、傳遞電壓等操作),這樣的介面設計方式有效地解耦了不同模組之間的依賴關係,使得整個系統的架構更加靈活、穩健,能夠更好地適應未來可能的功能變更和需求擴充套件,為系統的長期演進奠定了良好的基礎。

相關文章