OOP:对象之间的层次依赖关系

时间:2014-03-05 11:56:34

标签: php oop scope hierarchy

对于我正在解析和合并多个xml配置文件的项目。这些xml配置定义了块,这些块可能会也可能不会创建输出,这些选项在整个系统中都是可用的。块是分层的,这意味着:块可以容纳其他块。

(合并)配置可能如下所示:

<block name="root">

    <block name="sub">

        <block name="sub2">
            <option name="some-option" value="some-value" />
        </block>

        <option name="sub" value="value" />
    </block>

    <option name="key" value="value" />
    <remove name="sub" />
</block>

如您所见,块具有范围。这意味着:阻止sub仅在阻止root中可用,阻止sub2仅在阻止sub内可用。 但是:这些选项随处可用,但仅在包含块仍然存在的情况下。如您所见,最后一行包含remove'命令',它会从树中移除块sub,以及它的子项(块sub2和选项some-optionsub)。

如何维护层次结构对象结构并保持对元素范围的引用?

我探索了一些选项,比如分层对象结构:

class Block {
    private $parent = null; // reference to parent block, or 'null' if no parent exists
    private $children = array(); // list of children blocks
    private $options = array(); // list of options
    private $removes = array(); // list of remove 'commands'
}

甚至是嵌套集模型(带有左右值的sql模式)。

但无论我尝试什么,仍然会出现一些问题:

  1. “暂存”:如何为“全局范围”提供可用选项,删除等,但要跟踪它们的定义位置。例如:名称为“some-option”的选项应该可供系统的任何部分使用,除非它的包含块(“sub2”)被删除。
  2. “堆叠”:我需要存储所有“删除”选项,直到整个xml树被解析,然后它才会执行所有删除。应从外向内执行删除。这意味着如果在高级块(更靠近根)中找到了删除,则应首先执行删除,也可以从较低级别的块中删除remove指令。我有什么选择?对于每个移除存储,引用它的持有块(例如$remove[] = array('what-to-remove' => 'sub2', 'parent' => &$sub))?
  3. 我希望有人能指出我正确的方向!如果不清楚,请发表评论!

1 个答案:

答案 0 :(得分:0)

你可以使用一种Register类:

<?php

class Register {

    protected static $_instance;

    protected $_options = array();

    public static function getInstance() {
        if( null === self::$_instance ) {
            self::$_instance = new Register();
        }
        return self::$_instance;
    }

    // Assuming your option has a unique name
    public function registerOption( Option $option, Block $owner = null ) {
        $this->_options[$option->name] = array(
            'option' => $option,
            'owner'  => $owner
        );

        // Adds the option to the block if not exists
        if( null !== $owner && !$owner->hasOption($option) ) {
            $owner->addOption($option);
        }
    }

    public function removeOption( $optionName, $removeFromOwner = true ) {
        if( isset($this->_options[$optionName]) ) {
            if( $removeFromOwner ) {
                $owner = $this->_options[$optionName]['owner'];
                if( null !== $owner ) {
                    $owner->removeOption( $optionName );
                }
            }            

            unset( $this->_options[$optionName] );
        }

    }

}

在块中解析新选项时,可以通过调用Register :: getInstance() - &gt; registerOption($ option,$ owner)来注册它

在解析XML时,可以将删除命令堆叠在包含要删除的选项名称的数组中(假设选项名称是唯一的,如果它们不是唯一的,您可能必须解决此解决方案。)< / p>

解析完所有内容后,您可以取消删除删除命令并调用removeOption($ optionName)以从寄存器和拥有该选项的块中删除该选项。

我忘记了什么吗?