[toc]
## 舉個例子
> 網上買配件, 自己攢電腦
> 簡單組合, 即可使用, 沒有顯卡, 照樣能用
## 代碼示例
```php
<?php
// 組件,所有子配件的基類
class Component {
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function showInfo($indent = "") {
}
public function isComposite() {
return false;
}
public function startup($indent = "") {
echo $indent . $this->name . " 準備開始工作..." . PHP_EOL;
}
public function shutdown($indent = "") {
echo $indent . $this->name . " 即將結束工作..." . PHP_EOL;
}
}
// 中央處理器
class CPU extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "CPU: " . $this->name . ",可以進行高速計算。" . PHP_EOL;
}
}
// 內存條
class MemoryCard extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "內存: " . $this->name . ",可以緩存數據,讀寫速度快。" . PHP_EOL;
}
}
// 硬盤
class HardDisk extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "硬盤: " . $this->name . ",可以永久存儲數據,容量大。" . PHP_EOL;
}
}
// 顯卡
class GraphicsCard extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "顯卡: " . $this->name . ",可以高速計算和處理圖形圖像。" . PHP_EOL;
}
}
// 電源
class Battery extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "電源: " . $this->name . ",可以持續給主板和外接配件供電。" . PHP_EOL;
}
}
// 風扇
class Fan extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "風扇: " . $this->name . ",輔助CPU散熱。" . PHP_EOL;
}
}
// 顯示器
class Displayer extends Component {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent;
echo "顯示器:" . $this->name . ",負責內容的顯示。" . PHP_EOL;
}
}
// 配件組合器
class Composite extends Component {
protected $components;
public function __construct($name) {
parent::__construct($name);
$this->components = [];
}
public function showInfo($indent = '') {
echo $this->name . ",由以下部件組成:" . PHP_EOL;
$indent .= "\t";
foreach ($this->components as $element) {
$element->showInfo($indent);
}
}
public function isComposite() {
return True;
}
public function addComponent($component) {
array_push($this->components, $component);
}
public function removeComponent($component) {
$this->components = array_merge(array_diff($this->components, array($component)));
}
public function startup($indent = '') {
parent::startup($indent);
$indent .= "\t";
foreach ($this->components as $element) {
$element->startup($indent);
}
}
public function shutdown($indent = '') {
parent::startup($indent);
$indent .= "\t";
foreach ($this->components as $element) {
$element->shutdown($indent);
}
}
}
// 主板
class Mainboard extends Composite {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent . "主板: ";
parent::showInfo($indent);
}
}
// 機箱
class ComputerCase extends Composite {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent . "機箱: ";
parent::showInfo($indent);
}
}
// 電腦
class Computer extends Composite {
public function __construct($name) {
parent::__construct($name);
}
public function showInfo($indent = '') {
echo $indent . "電腦: ";
parent::showInfo($indent);
}
}
//測試代碼
$cpu = new CPU("Intel Core i5-6600K");
$memoryCard = new MemoryCard("Kingston Fury DDR4");
$hardDisk = new HardDisk("Kingston V300 ");
$graphicsCard = new GraphicsCard("Colorful iGame750");
$mainBoard = new Mainboard("GIGABYTE Z170M M-ATX");
$mainBoard->addComponent($cpu);
$mainBoard->addComponent($memoryCard);
$mainBoard->addComponent($hardDisk);
$mainBoard->addComponent($graphicsCard);
$battery = new Battery("Antec VP 450P");
$fan = new Fan("DEEPCOOL 120T");
$computerCase = new ComputerCase("SAMA MATX");
$computerCase->addComponent($battery);
$computerCase->addComponent($mainBoard);
$computerCase->addComponent($fan);
$displayer = new Displayer("AOC LV243XIP");
$computer = new Computer("Tony DIY電腦");
$computer->addComponent($displayer);
$computer->addComponent($computerCase);
$computer->showInfo("");
echo "\n開機過程:";
$computer->startup("");
echo "\n關機過程:";
$computer->shutdown("");
```
```
D:\soft\php72\php.exe D:\project\php_dp\index2.php
電腦: Tony DIY電腦,由以下部件組成:
顯示器:AOC LV243XIP,負責內容的顯示。
機箱: SAMA MATX,由以下部件組成:
電源: Antec VP 450P,可以持續給主板和外接配件供電。
主板: GIGABYTE Z170M M-ATX,由以下部件組成:
CPU: Intel Core i5-6600K,可以進行高速計算。
內存: Kingston Fury DDR4,可以緩存數據,讀寫速度快。
硬盤: Kingston V300 ,可以永久存儲數據,容量大。
顯卡: Colorful iGame750,可以高速計算和處理圖形圖像。
風扇: DEEPCOOL 120T,輔助CPU散熱。
開機過程:Tony DIY電腦 準備開始工作...
AOC LV243XIP 準備開始工作...
SAMA MATX 準備開始工作...
Antec VP 450P 準備開始工作...
GIGABYTE Z170M M-ATX 準備開始工作...
Intel Core i5-6600K 準備開始工作...
Kingston Fury DDR4 準備開始工作...
Kingston V300 準備開始工作...
Colorful iGame750 準備開始工作...
DEEPCOOL 120T 準備開始工作...
關機過程:Tony DIY電腦 準備開始工作...
AOC LV243XIP 即將結束工作...
SAMA MATX 準備開始工作...
Antec VP 450P 即將結束工作...
GIGABYTE Z170M M-ATX 準備開始工作...
Intel Core i5-6600K 即將結束工作...
Kingston Fury DDR4 即將結束工作...
Kingston V300 即將結束工作...
Colorful iGame750 即將結束工作...
DEEPCOOL 120T 即將結束工作...
Process finished with exit code 0
```
## 代碼說明
1. 組裝的電腦是由各個配件組成的,在組裝之前,就是一個個 CPU、硬盤、顯卡等配件,不能稱之為電腦
2. 只有把它們按正確的方式組裝在一起,配合操作系統才能正常運行。
3. 一般人使用電腦并不會關注內部的組成結構,只會關注一臺整機。
4. 這里有明顯的部分與整體的關系,主板、電源等是電腦的一部分,而主板上又有 CPU、硬盤、顯卡,它們又可以認為是主板的一部分。
## 什么是組合模式?
> 像電腦一樣,把對象組合成樹形結構,以表示“部分-整體”的層次結構的程序設計模式就叫組合模式。
> 組合模式使得用戶對單個對象和組合對象的使用具有一致性,使用組合對象就像使用單個對象一樣,不用關心內部的組織結構。
> 組合模式是一個非常常用的模式,你可能在有意或無意間就已經用上了,比如公司(各個部門或各個子公司)的組織架構,學校各個學院-班級的關系


## 優缺點
**組合模式的優點**
1. 調用簡單,組合對象可以像一般對象一樣使用。
1. 組合對象可以自由地增加、刪除組件,可靈活地組合不同的對象。
**組合模式的缺點**
1. 在一些層次結構太深的場景中,組合結構會變得太龐雜(本質是樹形結構)。
## 應用場景
1. 對象之間具有明顯的“部分-整體”的關系時,或者具有層次關系時。
1. 組合對象與單個對象具有相同或類似行為(方法),用戶希望統一地使用組合結構中的所有對象。