# Chapter 26 主元件 The Main Component ![](https://i.imgur.com/UkCGDn6.png) 每個系統中,都會至少有一個元件是用來建立、協調、監督其他的元件。我們稱之為 Main。 ## The Ultimate Detail Main 元件就是最終的細節,也是最低層次的策略 (lowest-level policy)。 這是系統的初始入口點。除了作業系統,沒有東西依賴它。 它的任務是建立所有的工廠 (factories)、策略 (strategies)、和其他全域設施 (global facilities),再將控制權交給系統高層抽象部分。 在 Main 元件中,依賴關係應由依賴注入框架 (Dependency Injection framework) 注入。一但他們被注入到 Main,Main 就能在不使用框架的情況下,如平常時那樣配置這些依賴關係。 可以把 Main 想像成所有髒元件當中最髒的元件。 以下是Hunt the Wumpus當中的 Main 元件。注意他如何載入所有我們不希望程式碼主體知道的字串。 ``` static void Main(string[] args) { HuntTheWumpus game; int hitpoints = 10; List<String> caverns = new List<string>(); String[] environments = new string[] { "bright", "humid", "dry", "creepy", "ugly", "foggy", "hot", "cold", "drafty", "dreadful"}; String[] shapes = new string[] {" round", "scruare", "oval", "irregular", " long", "craggy", "rough", "tali", "narrow"}; string[] cavernlypes = new string[] {"cavern", "room", "chamber", "catacomb", "crevasse", "cell", "tunnel", "passageway" , "hall", "expanse"}; String[] adornments = new String[] { "smelling of sulfur", "with engravings on the walls", "with a bumpy floor", "ม่it red with garbage", "spatte ered with guano", "with piles of wumpus droppings", "with bones scattered around", "with a a corpse on the floor", "that seems to vibrate", "that feels stuffy", "that fills you with dread" }; } ``` 現有一個 main 函式如下。注意它是如何使用 HtwFactory 建立遊戲的。 它透過傳入這個類別的名稱,htw.game.HuntTheWupusFacade,因為那個類別甚至比 Main 更髒,這樣就能防止該類別的更改導致 Main 的重新編譯/部屬。 ``` static void Main1(string[] args) { game = HtwFactory.makeGame("htw.game.Hunt ThewumpusFacade",new Main()); createMap(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); game.makeRestCommand().execute(); while (true) ( system.out.printin(game e.getplayerCavern()); system.out.Printin("Health: " + hitPoints + " arrows: " + game.getQuiver()); HuntTheWumpus.Command c = game.makeRestCommand(); system.out.printin(">"); String command = br.readLine(); if (command.equalsIgnoreCase("e")) c = game.makeMoveCommand(EAST); else if (command.egualsIgnoreCase("w")) c = game.makeMoveCommand(WEST); else if (command.ecualsIgnoreCase("n")) c = game.makeMoveCommand(NORTH); else if (command.ecualsIgnoreCase("s")) c = game.makeMoveCommand(SOUTH); else if (command.equalsIgnoreCase("r")) c = game.makeRestCommand(); else if (command.equalsIgnoreCase("sw")) c = game.makeShootCommand(WEST); else if (command.equalsIgnoreCase("se")) c = game.makeShootCommand(EAST); else if (command.equalsIgnoreCase("sn")) c = game.makeShootCommand(NORTH); else if (command.equalsIgnoreCase("ss")) c = game.makeShootCommand(SOUTH); else if (command.equalsIgnoreCase("q")) return; c.execute(); } ``` main 建立輸入流並包含遊戲的主迴圈,解譯簡單的輸入命令,並將處理延緩到其他更高層級的元件。 最後,請注意到 main 建立了地圖 ``` static void createMap() { int nCaverns = (int)(Math.random() * 30.0 + 10.0); while (nCaverns-- > 0) caverns.add(makeName()); for (String cavern : caverns) { maybeConnectCavern(cavern, , NORTH); maybeConnectCavern(cavern, SOUTH); maybeConnectCavern(cavern, EAST); maybeConnectCavern(cavern, wEsT); } String playerCavern = anyCavern(); game.setplayerCavern(playerCavern); game.setwumpusCavern(anyOther(playerCavern)); game.addBatCavern(anyother(playerCavern)); game.addBatCavern(anyOther(playerCavern)); game.addBatCavern(anyother(playerCavern)); game.addPitCavern(anyother(playerCavern)); game.addPitCavern(anyother(playerCavern)); game.addPitCavern(anyOther(playerCavern)); game.setQuiver(5); } ``` 重點在於 Main 是位於整潔架構 (clean architecture) 最外圈的一個髒的低層級模組。 它將所有內容載入到高層級系統中,接著將控制權轉交給高層系統。 Conclusion 我們可以將 Main 當作是一種 plugin,一種用來設定初始條件 (initial condition) 與設置 (configurations),並蒐集外部資源 (outside resources),然後將控制權轉移到程式的高級策略。 由於它是一個 plugin,所以可能有許多的 Main元件(每個應用程式的設置都有一個,ex: Dev、Test、Production…)。 當你將 Main 看做一個躲在架構邊界之後的 plugin 元件時,設置問題 (problem of configuration) 就變得更容易解決了。