當(dāng)我們的一個(gè)對(duì)象可能代表一個(gè)單一的實(shí)體,或者一個(gè)組合的實(shí)體,但是仍然需要通過(guò)同樣的方式被使用時(shí),這種情形則適合使用組合模式的設(shè)計(jì)。
組合模式Composite將對(duì)象組合成樹(shù)形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

適用性:
當(dāng)需求中是體現(xiàn)部分與整體層次的結(jié)構(gòu)時(shí),以及你希望用戶可以忽略組合對(duì)象與單個(gè)對(duì)象的不同,統(tǒng)一地使用組合結(jié)構(gòu)中的所有對(duì)象時(shí),就應(yīng)該考慮用組合模式。
角色:
樹(shù)干——基類、樹(shù)枝——組合對(duì)象、樹(shù)葉——局部對(duì)象
例:
abstract class CompanyBase{
??? //節(jié)點(diǎn)名稱
??? protected $name;
??? public function _construct($name){
??????? $this->name = $name;
??? }
??? public function getName(){
??????? return $this->name;
??? }
??? //增加節(jié)點(diǎn)
??? abstruct function add(CompanyBase $c);
??? //刪除節(jié)點(diǎn)
??? abstruct function remove(CompanyBase $c);
??? //輸出節(jié)點(diǎn)信息
??? abstruct function show($deep);
??? //節(jié)點(diǎn)職責(zé)
??? abstruct function work($deep);
}
//公司類
class Company extends CompanyBase{
??? protected $item = [];
??? public function add(){
??????? $nodeName = $c->getName();
??????? if(!isset($this->item[$nodeName])){
??????????? $this->item[$nadeName] = $c;
??????? }else{
??????????? throw new Exception("該節(jié)點(diǎn)已存在,節(jié)點(diǎn)名稱:".$nodeName);
??????? }
??? }
??? public function remove(CompanyBase $c){
??????? $nodeName = $c->getName();
??????? if(isset($this->item[$nodeName])){
??????????? unset($this->item[$nodeName]);
??????? }else{
??????????? throw new Exception("該節(jié)點(diǎn)不存在,節(jié)點(diǎn)名稱:".$nodeName);
??????? }
??? }
??? public function show($deep=0){
??????? echo str_repeat("-",$deep).$this->name;
??????? echo "<br>";
??????? foreach($this->item as $value){
??????????? $value->show($deep+4);
??????? }
??? }
??? public function work($deep = 0){
??????? foreach($this->item as $value){
??????????? echo str_repeat("$emsp",$deep)."[{$this->name}]<br>";
??????????? $value->work($deep+2);
??????? }
??? }
/*
*人力資源部
*/
class HumanResources extends CompanyBase{
??? public function add(CompanyBase $c){
??????? throw new Exception("該節(jié)點(diǎn)下不能增加節(jié)點(diǎn)");
??? }
??? public function remove(CompanyBase $c){
??????? throw new Exception("該節(jié)點(diǎn)下無(wú)子節(jié)點(diǎn)");
??? }
??? public function show($deep = 0){
??????? echo str_repeat("-", $deep).$this->name;
??????? echo "<br>";
??? }
??? public function work($deep = 0){
??????? echo str_repeat("?", $deep)."人力資源部門的工作是為公司招聘人才";
??????? echo "<br>";
??? }
}
/*
*商務(wù)部門
*/
class Commerce extends CompanyBase{
??? public function add(CompanyBase $c){
??????? throw new Exception("該節(jié)點(diǎn)下不能增加節(jié)點(diǎn)");
??? }
??? public function remove(CompanyBase $c){
??????? throw new Exception("該節(jié)點(diǎn)下無(wú)子節(jié)點(diǎn)");
??? }
??? public function show($deep = 0){
??????? echo str_repeat("-", $deep).$this->name;
??????? echo "<br>";
??? }
??? public function work($deep = 0){
??????? echo str_repeat("?", $deep)."商務(wù)部門的工作是為公司賺取利潤(rùn)";
??????? echo "<br>";
??? }
}
$c = new Company("北京某科技公司");
$h = new HumanResources("人力資源部門");
$com = new Commerce("商務(wù)部門");
$c->add($h);
$c->add($com);
//天津分公司
$c1 = new Company("天津分公司");
$c1->add($h);
$c1->add($com);
$c->add($c1);
//武漢分公司
$c2 = new Company("武漢分公司");
$c2->add($h);
$c2->add($com);
$c->add($c2);
$c->show();
$c->work();
特點(diǎn):
1、必須存在不可分割基本元素。
2、組合后的物體可以被組合。