概述#

物件導向設計(OOD)題目要求應試者描繪出解決技術問題或現實物件的 class 架構與方法。這類題目考驗的是你能否設計出優雅、可維護的物件導向程式碼,而非你是否記得設計模式。表現不佳可能會被列為嚴重警訊。

How to Approach(解題步驟)#

無論是設計實體物件還是軟體系統,以下四個步驟適用於大多數 OOD 問題。

Step 1: Handle Ambiguity(釐清模糊性)#

OOD 題目通常是故意模糊的,用來測試你是否會主動問問題、還是直接假設並動手寫程式。一個不了解需求就寫程式的工程師,會浪費公司的時間和金錢,甚至造成更嚴重的問題。

面對 OOD 題目,應詢問:

  • Who:誰會使用這個系統?
  • How:他們如何使用它?
  • 必要時可用「六個 W」框架:who, what, where, when, how, why

範例:設計一個咖啡機的物件導向結構。

  • 是每小時服務數百位顧客、提供十種咖啡的工業用機器?
  • 還是供老人使用的簡單家用機,只做黑咖啡?
  • 使用情境不同,設計就完全不同。

Step 2: Define the Core Objects(定義核心物件)#

釐清需求後,思考系統中的「核心物件」是什麼。

範例:設計餐廳的 OOD。核心物件可能包括:

  • TableGuestPartyOrderMealEmployeeServerHost

Step 3: Analyze Relationships(分析關係)#

確定核心物件後,分析它們之間的關係:

  • 哪些物件是哪些物件的成員(has-a)?
  • 哪些物件繼承自哪些物件(is-a)?
  • 關係是一對多還是多對多?

餐廳範例的關係設計:

  • Party 應有一個 Guest 陣列
  • ServerHost 繼承自 Employee
  • 每個 Table 有一個 Party,但每個 Party 可能有多個 Table
  • Restaurant 有一個 Host

要小心不要做錯誤假設。例如,一個 Table 可能同時屬於多個 Party(如時髦餐廳的共桌制)。應與面試官確認設計的通用程度。

Step 4: Investigate Actions(考察行為)#

此時已有基本架構,接下來思考物件之間的關鍵動作,以及這些動作如何影響設計。你可能會發現遺漏了某些物件,需要更新設計。

範例

  • 一個 Party 走進 RestaurantGuestHost 要求一張 Table
  • Host 查詢 Reservation,若存在則分配 TableParty
  • 若不存在,Party 加入等候名單
  • Party 離開,Table 被釋放並分配給下一個 Party

Design Patterns(設計模式)#

面試官評估的是你的能力,而非你對設計模式的記憶。設計模式的範疇遠超出面試所需。但 SingletonFactory Method 這兩個模式在面試中較常見,因此在此介紹。

不要陷入「一定要找到某個設計模式來套用」的陷阱。設計應該解決眼前的問題。有時答案剛好符合某個模式,更多時候並不是。

Singleton Class(單例模式)#

Singleton 確保一個 class 只有唯一實例,並提供全域存取點。適合用於需要全域唯一物件的場景。

public class Restaurant {
    private static Restaurant _instance = null;
    protected Restaurant() { ... }
    public static Restaurant getInstance() {
        if (_instance == null) {
            _instance = new Restaurant();
        }
        return _instance;
    }
}

許多人不喜歡 Singleton 模式,甚至稱其為「anti-pattern」。原因之一是它會干擾單元測試。

Factory Method(工廠方法模式)#

Factory Method 提供建立物件的介面,讓子類別決定要實例化哪個 class。可以讓 creator class 為抽象類別(不提供實作),或是提供一個接受參數決定實例化哪個 class 的具體方法。

public class CardGame {
    public static CardGame createCardGame(GameType type) {
        if (type == GameType.Poker) {
            return new PokerGame();
        } else if (type == GameType.BlackJack) {
            return new BlackJackGame();
        }
        return null;
    }
}

本章面試題列表#

題號題目頁碼
7.1Deck of Cards(設計撲克牌資料結構)pg 305
7.2Call Center(設計客服中心呼叫系統)pg 307
7.3Jukebox(設計音樂點播機)pg 310
7.4Parking Lot(設計停車場)pg 312
7.5Online Book Reader(設計線上書籍閱讀系統)pg 318
7.6Jigsaw(設計 NxN 拼圖)pg 318
7.7Chat Server(設計聊天伺服器)pg 326
7.8Othello(設計黑白棋遊戲)pg 326
7.9Circular Array(實作可高效旋轉的環形陣列)pg 329
7.10Minesweeper(設計踩地雷遊戲)pg 332
7.11File System(設計記憶體內檔案系統)pg 337
7.12Hash Table(設計使用 chaining 的 Hash Table)pg 338