若转载教程,请注明出自SW-X框架官方文档!

    1. <?php
    2. /**
    3. * 设计模式之组合器模式
    4. * 定义:将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性
    5. * 我的理解:把对象构建成树形结构
    6. * 小黄牛
    7. */
    8. header("Content-type: text/html; charset=utf-8");
    9. /**
    10. * 抽象 - 枝节点与叶子节点都要实现的接口
    11. */
    12. abstract class Company{
    13. protected $name; // 节点名
    14. function __construct($name){
    15. $this->name = $name;
    16. }
    17. public function Add($composite){} // 增加一个节点对象
    18. public function Delete($composite){} // 删除一个节点对象
    19. public function Dump($length){} // 打印对象组合
    20. }
    21. /**
    22. * 具体化 - 枝节点 - 公司
    23. */
    24. class SubCompany extends Company{
    25. private $sub_companys = array(); // 节点对象组合器
    26. # 添加节点名称
    27. public function __construct($name){parent::__construct($name);}
    28. # 增加一个节点对象
    29. public function Add($company){ $this->sub_companys[] = $company;}
    30. # 删除一个节点对象
    31. public function Delete($company){
    32. $key = array_search($company, $this->sub_companys);
    33. if(false !== $key){
    34. unset($this->sub_companys[$key]);
    35. }
    36. }
    37. # 打印对象组合
    38. public function Dump($length = 1){
    39. $hr = '├';
    40. for ($i=0; $i<$length; $i++){
    41. $hr .= "─";
    42. }
    43. echo $hr.$this->name. "<br/>";
    44. foreach($this->sub_companys as $val){
    45. $val->Dump($length+1); // 让叶子节点继续打印,这一步+1很重要
    46. }
    47. }
    48. }
    49. /**
    50. * 具体化 - 叶子节点 - 部门
    51. */
    52. class Dept extends Company{
    53. # 添加节点名称
    54. public function __construct($name){parent::__construct($name);}
    55. # 增加一个节点对象
    56. public function Add($company){echo '叶子节点,不给你再添加节点....当然你自己可以看需求定义结构层级<br/>';}
    57. # 删除一个节点对象
    58. public function Delete($company){echo '叶子节点,不给你删除节点....当然你自己可以看需求定义结构层级<br/>';}
    59. # 打印对象组合
    60. public function Dump($length){
    61. $hr = '├';
    62. for ($i=0; $i<$length; $i++){
    63. $hr .= "─";
    64. }
    65. echo $hr.$this->name. "<br/>";
    66. }
    67. }
    68. # 创建一级根节点
    69. $root = new SubCompany('总部');
    70. $root->Add(new Dept("财务部"));
    71. $root->Add(new Dept("技术部"));
    72. $root->Add(new Dept("商务部"));
    73. $root->Add(new Dept("采购部"));
    74. $root->Dump();
    75. echo '<br/>';
    76. # 创建二级节点,实际上在没有关联到总部之前,分公司还是一级节点
    77. $guangzhou = new SubCompany('广州分公司');
    78. $guangzhou->Add(new Dept("分公司财务部"));
    79. $guangzhou->Add(new Dept("分公司技术部"));
    80. $guangzhou->Add(new Dept("分公司商务部"));
    81. $guangzhou->Add(new Dept("分公司采购部"));
    82. $guangzhou->Dump();
    83. echo '<br/>';
    84. # 向一级节点关联二级节点
    85. $root->Add($guangzhou);
    86. $root->Dump();

    浏览器输出

    1. ─总部
    2. ├──财务部
    3. ├──技术部
    4. ├──商务部
    5. ├──采购部
    6. ├─广州分公司
    7. ├──分公司财务部
    8. ├──分公司技术部
    9. ├──分公司商务部
    10. ├──分公司采购部
    11. ├─总部
    12. ├──财务部
    13. ├──技术部
    14. ├──商务部
    15. ├──采购部
    16. ├──广州分公司
    17. ├───分公司财务部
    18. ├───分公司技术部
    19. ├───分公司商务部
    20. ├───分公司采购部

    组合器模式

    1. 抽象结构(Company)角色:此角色实现所有类共有接口的默认行为,声明一个接口管理子部件。
    2. 叶子节点(Technology)角色:表示叶子对象,没有子节点。
    3. 枝节点(SubCompany)角色:用来存储子部件,实现与子部件有关的操作,如Add()等。

    优势

    1. 组合模式让你可以优化处理递归或分级数据结构。有许多关于分级数据结构的例子,使得组合模式非常有用武之地。关于分级数据结构的一个普遍性的例子是你每次使用电脑时所遇到的:文件系统。文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。如果你想要描述这样的数据结构,那么你可以使用组合模式Composite

    应用场景

    1. 需用使用到树结构保存数据的情况下