組合模式(Composite Pattern),又叫部分整體模式,是用於把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬於結構型模式,它創建了對象組的樹形結構。
意圖
將對象組合成樹形結構以表示”部分-整體”的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
解決問題
它在我們樹型結構的問題中,模糊了簡單元素和複雜元素的概念,客戶程序可以像處理簡單元素一樣來處理複雜元素,從而使得客戶程序與複雜元素的內部結構解耦。
UML圖

該模式包含的角色及其職責
抽象根節點(Component)
定義系統各層次對象的共有方法和屬性,可以預先定義一些默認行為和屬性。
樹枝節點(Composite)
定義樹枝節點的行為,存儲子節點,組合樹枝節點和葉子節點形成一個樹形結構。
葉子節點(Leaf)
葉子節點對象,其下再無分支,是系統層次遍歷的最小單位。
在本例子中:

優缺點
優點
- 複雜的對象分層次表示,添加新的節點容易。
- 客戶端調用簡單,客戶端可以一致的使用組合結構或其中單個對象。
- 更容易在組合體內加入對象構件,客戶端不必因為加入了新的對象構件而更改原有代碼。
缺點
- 在使用組合模式時,其葉子和樹枝的聲明都是實現類,而不是接口,違反了依賴倒置原則。
- 使設計變得更加抽象,對象的業務規則如果很複雜,則實現組合模式具有很大挑戰性,而且不是所有的方法都與葉子對象子類都有關聯。
應用場景
- 當想表達對象的部分-整體的層次結構時,如公司的上下級關係,分銷系統,產品品牌分類。
- 希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象時。
案例背景
舉一個例子:一家公司的組成通常都是多個部門組成的,現在我們有一家公司有多個部門,部門裏面還有很多職位,我們用這個組合模式來看看。
組織架構

使用代碼把上圖轉換成下圖的形式表達

應用場景
Component.php 抽象的公司架構(Component)
abstract class Component
{
protected $name;
/**
* Component constructor.
* @param $name
*/
public function __construct($name){
$this->name = $name;
}
public abstract function operation($depth);
public abstract function add(Component $component);
public abstract function remove(Component $component);
}Composite.php 具體的公司部門(Composite)
class Composite extends Component
{
private $componentList;
public function operation($depth){
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
foreach ($this->componentList as $component) {
$component->operation($depth + 2);
}
}
public function add(Component $component){
$this->componentList[] = $component;
}
public function remove(Component $component){
$position = 0;
foreach ($this->componentList as $child) {
++$position;
if ($child == $component) {
array_slice($this->componentList, $position, 1);
}
}
}
public function getChild(int $i){
return $this->componentList[$i];
}
}Leaf.php 公司部門最終的職位(Leaf)
class Leaf extends Component
{
public function operation($depth){
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
}
public function add(Component $component){
echo "Cannot add to a leaf".PHP_EOL;
}
public function remove(Component $component){
echo "Cannot remove from a leaf".PHP_EOL;
}
}調用代碼:
$root = new Composite("公司");
// 添加人事部門
$rs = new Composite("人事部門");
// 添加人事部門下面的職位
$rs->add(new Leaf("人事總監"));
$rs->add(new Leaf("人事主管"));
$rs->add(new Leaf("人事專員"));
$root->add($rs);
// 添加財務部門
$cw = new Composite("財務部門");
// 添加部門下面的職位
$cw->add(new Leaf("財務總監"));
$cw->add(new Leaf("會計"));
$cw->add(new Leaf("出納"));
$root->add($cw);
$root->operation(0);
$child = $root->getChild(0);
print_r($child);輸出結果:
公司
--人事部門
----人事總監
----人事主管
----人事專員
--財務部門
----財務總監
----會計
----出納
// 通過 getChild 獲取的某個部門對象
Composite Object
(
[Composite:private] => Array
(
[0] => Leaf Object
(
[name:protected] => 人事總監
)
[1] => Leaf Object
(
[name:protected] => 人事主管
)
[2] => Leaf Object
(
[name:protected] => 人事專員
)
)
[name:protected] => 人事部門
)如果覺得文章還不錯,請把文章分享給更多的人學習,在文章中發現有誤的地方也希望各位指出更正。現有誤的地方也希望各位指出更正。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/259086.html
微信掃一掃
支付寶掃一掃