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



对于一个项目,我正在分析和合并多个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. "Stacking":我需要存储所有的"remove"选项,直到解析完整个xml树,然后它才应该执行所有的remove。删除应在中从外部执行。这意味着,如果在高级块(离根更近)中发现了remove,则应首先执行它,可能会从较低级别的块中删除remove指令。我有什么选择?对于每个移除存储,是否引用其保存块(例如$remove[] = array('what-to-remove' => 'sub2', 'parent' => &$sub))

我希望有人能给我指明正确的方向!如果有什么不清楚的地方,请评论!

您可能可以使用这样一种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()->registerOption($option,$owner)来注册它

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

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

我忘了什么吗?

最新更新