情况:我正在构建自定义 PHP 应用程序框架。我已经实现了一个复合模式,所以我可以构建一个对象树来表示要呈现的页面。示例:
abstract class \Block\BlockAbstract {
protected _blocks = array();
public function __construct($properties);
public function getBlocks();
public function addBlock($block);
...
}
我所有的“ block ”对象都继承自这个抽象类,它运行良好,在一点递归的帮助下渲染变得轻而易举。
问题: 我需要一种方法来验证哪些类的 block 可以添加到其他 block 中。例如,我必须考虑 4 种不同的 block 类型。请记住,所有 block 都继承自单个 block 抽象,这些是具体类的行为分类,不要与其他抽象混淆:
泛型 - 泛型可以添加任何其他 block 类型
Final - 不能添加任何子 block 。
父级 - 父级是一个只能添加特定类型子级的 block 它,但可以添加到任何通用
子项 - 只能添加到特定的父项。此 block 还可以共享 Generic、Parent 或 Final 的属性
总结一下目标:给定一个具体的 block 类名称,生成一个包含所有可以添加到它的具体 block 类的列表。
目前提出的解决方案:
将名为“blockClassification”的属性添加到将其定义为通用、最终、父级或子级的 block 抽象,并将逻辑硬编码到验证函数中,该函数在 addBlock($block) 中调用方法。
出于多种原因我不喜欢这个解决方案,但主要是它仍然没有给我一个明确的途径来定义可以允许的具体 parent 和 child 是什么。例如,我有一个作为父类的具体类 \Block\Tabs。它只能添加\Block\Tabs\Panel block ,\Block\Tabs\Panel只能添加到\Block\Tabs。必须添加额外的属性来建立这些关系,并且可以检查这些属性来导出“ block 分类”,这使得这种方法不切实际。
将 allowedChildTypes 属性添加到定义可添加的具体类列表的 block 中。为了便于使用,2个值有特定的含义,*表示所有 block 类型,NULL值表示不能添加 block 。对于所有其他情况,提供逗号分隔的类名字符串,并且只允许那些类或从它们继承的类
我倾向于这个方向,因为 PHP 为我提供了 InstaceOf 运算符。我可以使用它来进行检查,当我有扩展基集的新具体类时,该检查将返回与其父类相同的结果。我唯一的犹豫是,虽然这种方法确实解决了“给定一个具体的 block 类名称,生成一个列表”的问题,但我觉得它在未来限制了我,因为我只能在树下进行搜索而不能返回向上。 IE。 “给定子 block 类名,生成可以添加到的父 block 列表”
我确信我不是唯一遇到过这个问题的人,所以我向大众提出的问题是:处理/解决这个问题的最佳方法是什么?
附加信息:
如果您想知道我首先是如何获得所有类的列表的,框架实现了 PSR-0,所以我正在扫描目录树以派生所有类名,然后动态实例化它们。
$allClassNames = scanDirectories(); // Returns array of strings ex: array('\Block\Classname1','\Block\Classname2');
foreach($allClassNames as $className){
$object = new $className();
}
最佳答案
越来越多地思考这个问题,我认为可能有另一种方法来抽象它。
通用、最终、父和子类别似乎可以分为三个部分:通用、最终和自定义(其中父或子是特定的)
这三个部分可以用两个属性来解释:parent 和 child。
考虑一下:
parent child generic / * final /blocks/tabs null parent /blocks/ /blocks/tabs/ child (generic) /blocks/tabs/ * child (final) /blocks/tabs/ null child (parent) /blocks/tabs/ /blocks/popup/
- generic block 有 parent/,作为根,可以有任何类型的 child
- 最后一个 block 是/blocks/tabs/的子 block (因此下一个 block 示例,父 block ,可以将它作为子 block )并且不能有任何子 block
- 父 block 可以添加到任何 block ,并且可以在标签中有子 block
- child 可以附加到标签
- 普通 child 可以有任何 child
- 最后一个 child 不能有任何 child
- parent child 可以有popup child
给定一个特定的 block ,您可以找到其父或子属性等于特定父或子属性的通用 block
关于php - 使用复合模式限制可以相互添加的对象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23683731/