# Chapter 26 主元件 The Main Component

每個系統中,都會至少有一個元件是用來建立、協調、監督其他的元件。我們稱之為 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) 就變得更容易解決了。