组合模式的实际用处-文件系统

时间:2022-10-14 22:46:52
组合模式让你可以优化处理递归或分级数据结构。

有许多关于分级数据结构的例子,使得组合模式非常有用武之地。

关于分级数据结构的一个普遍性的例子是你每次使用电脑时所遇到的:文件系统。

文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。

如果你想要描述这样的数据结构,那么你可以使用组合模式Composite。
三大角色:

抽象结构(Company)角色:此角色实现所有类共有接口的默认行为,声明一个接口管理子部件。

叶子节点(Technology)角色:表示叶子对象,没有子节点。

枝节点(SubCompany)角色:用来存储子部件,实现与子部件有关的操作,如Add()等。
<?php
//写一个表示菜单和菜单选项之间相似性的抽象类
abstract class MenuComp
{
    protected $marked=FALSE;//标识状态
    protected $label;

    public function mark(){$this->marked=TRUE;}//设置标记状态
    public function ismark(){return $this->marked;}//返回标记状态

    public function setLabel($label){ $this->label=$label;}//设置标签
    public function getLabel(){ return $this->label;}//返回标签

    abstract public function hasMenuOptionId($id);//抽象方法用来标识ID
    abstract public function MarkPathToMenuOption($id);//抽象方法用来标识菜单路径
}

class menu extends MenuComp
{
    protected $marked=false;//标记状态
    protected $label;//菜单标签
    private $children=array();//子菜单或子菜单选项数组
    private $id;//菜单ID

    public function __construct($label,$id)//构造函数用来设置标签和ID
    {
        $this->label=$label;
        $this->id=$id;
    }

    public function add($child)//添加菜单
    {
        $this->children[]=$child;
    }

    public function hasMenuOptionId($id)//用迭代方式询问所有子对象上是否有对应ID的菜单选项
    {
        foreach ($this->children as $child)
        {
            if ($child->hasMenuOptionID($id))
                return TRUE;
        }
        return FALSE;
    }

    public function MarkPathToMenuOption($id)//用迭代方式标记路径
    {
        if (!$this->hasMenuOptionId($id))
            return FALSE;
        $this->mark();
        foreach ($this->children as $child)//用迭代方式
        {
            $child->MarpathToMenuOption($id);
        }
    }
}

class menuOption extends MenuComp //菜单选项类
{
    protected $marked=false;//标记状态
    protected $label;//菜单标签例如:www.chhua.com
    private $id;//菜单ID

    public function __construct($label,$id)//构造函数用来设置标签和ID
    {
        $this->label=$label;
        $this->id=$id;
    }

    public function hasMenuOptionId($id)
    {
        return $id==$this->id;
    }

    public function MarkPathToMenuOption($id)
    {
        if ($this->hasMenuOptionId($id))
            $this->mark();
    }
}

?>