封裝(Encapsulation)能解決什麼問題? — 用 TypeScript 學物件導向

林鼎淵
Dean Lin
Published in
Aug 23, 2022

市面上很多文章、影片分享了物件導向要如何應用。

卻很少人分享這些概念是為了解決什麼問題,所以很多人就算學完了物件導向的概念,卻依舊沒有把它應用在手上的專案。

因此這個系列文中,筆者會先分享「直線思考下」我們會設計出怎樣糟糕的程式;接著再來討論如何應用物件導向的概念對程式做 Refactoring,提升程式未來的擴充性、維護性。

大綱一、設計考卷二、如果考卷的 Class 也被其他工程師使用三、我們希望在「設定答案」時通知其他老師四、老闆…我改不動了,打算用封裝進行重構五、所以「封裝(Encapsulation)」這個概念幫我們解決了什麼問題?

一、設計考卷

假使我們今天要製作一個線上考試的系統,相信「考卷」是考試的必要元素之一,今天我們就用它來舉例,說明「封裝」的重要性。

這邊我們先簡單定義「考卷(ExaminationPaper)」該有的屬性,像是「試卷名稱(name)、題目(questions)、答案(answers)」。

如果我們想要使用裡面的屬性,只要透過 new 將它實體化,接著用「.」就能夠存取使用,像是下面的範例中我們新增了一份「數學」考卷。

二、如果考卷的 Class 也被其他工程師使用

上面直接給考卷「試卷名稱、題目、解答」的方式看起來是不是很清爽?

但如果今天這個系統除了你之外,還有其他的工程師也使用了這個考卷的 Class,在其他檔案去新增諸如「英文、國文、歷史…」的考卷,你覺得未來可能會發生什麼問題呢?

三、我們希望在「設定答案」時通知其他老師

今天設想一個情境,老師可能在出完考卷後發現提供的答案寫錯了,因此需要修改試卷答案;而校方為了確保試卷答案的正確性,希望系統可以在「設定答案」時發信通知其他老師,讓大家確認答案是否正確。

好的,此時身為工程師的你會怎麼做?

去搜尋所有「examinationPaper.answers」的程式,然後在後面加上「sendEmail」的函式嗎?

如果你真的採用上面的做法,假使這個試卷的 Class 被引用 100 次,那就需要在那 100 個地方新增「sendEmail」的函式;這個做法不但會增加日後程式維護的困難度,要是不久後校方要求「設定答案時,需要先經過審核」,那你就會改到想死吧?

系統在設計時,就需要考慮到未來的擴充性;否則在需求變更時會死得很慘。

四、老闆…我改不動了,打算用封裝進行重構

過去我們把「name、questions、answers」都設定為 public 可以直接存取,但就如同上面的範例,正因為可以「直接存取」而導致未來程式擴充性的問題。

因此在重構上,我們將「name、questions、answers」改為 private,如果想要存取則要透過 Getters、Setters 的函式。

重構後,儘管我們 ExaminationPaper 的 Class 變得更長,但是日後有其他需求新增時,我們可以更靈活的變更,維護性、可讀性、擴充性都增加不少。

以今天重構後的 Class 舉例,如果日後使用到設定答案:

examinationPaper.answers = [...];

就會觸發到 sendEmail 的函式。

五、所以「封裝(Encapsulation)」這個概念幫我們解決了什麼問題?

  1. 透過封裝,我們可以保護 Class 屬性,不讓人隨意修改。
  2. 資料讀取、變更,透過 Getters、Setters 統一處理。
  3. 因為把方法封裝,所以在需求變更時,只要修改一個地方,不需要在每個用到的地方都修改。
▶︎ 用 TypeScript 學物件導向▋ 封裝(Encapsulation)能解決什麼問題?(本篇)
多型(Polymorphism)&繼承(Inheritance)能解決什麼問題?
▶︎ 如果這篇文章有幫助到你1. 可以點擊下方「Follow」來追蹤我~
2. 可以對文章拍手讓我知道 👏🏻
你們的追蹤與鼓勵是我繼續寫作的動力 🙏🏼▶︎ 如果你對工程師的職涯感到迷茫1. 也許我在iT邦幫忙發表的系列文可以給你不一樣的觀點 💡
2. 也歡迎您到書局選購支持,透過豐富的案例來重新檢視自己的職涯

--

--

林鼎淵
Dean Lin

職涯中培育過多名工程師,🧰 目前在外商公司擔任 Software Specialist |✍️ 我專注寫 (1)最新技術 (2)團隊合作 (3)工程師職涯的文章,出版過 5 本專業書籍|👏🏻 如果對這些主題感興趣,歡迎點擊「Follow」來關注我~