【发布时间】:2018-09-04 11:36:21
【问题描述】:
我有一组对象 (MainObject),它们由两个对象 (SubObject1、SubObject2) 和一个字符串 (theString) 唯一定义。我通过返回一个基于两个子对象和字符串的现有对象来从集合中检索MainObject,如果它存在,则创建一个新对象,将其添加到集合中,然后返回该对象。
以下伪代码在标准数组可以使用对象作为键的假想世界中演示了这一点。
class SubObject1{}
class SubObject2{}
class MainObject{
private $subObject1, $subObject2, $theString;
public function __construct(SubObject1 $subObject1, SubObject2 $subObject2, string $theString):MainObject {
$this->subObject1=$subObject1;
$this->subObject2=$subObject2;
$this->theString=$theString;
}
}
class ObjectCollection
{
private $map=[];
public function getObject(SubObject1 $subObject1, SubObject2 $subObject2, string $theString):MainObject {
if(isset($this->map[$subObject1][$subObject2][$theString])) {
$mainObject=$this->map[$subObject1][$subObject2][$theString];
}
else {
$mainObject=new MainObject($subObject1, $subObject2, $theString);
$this->map[$subObject1][$subObject2][$theString]=$mainObject;
}
return $mainObject;
}
}
$objectCollection=new ObjectCollection();
$subObject1_1=new SubObject1();
$subObject1_2=new SubObject1();
$subObject2_1=new SubObject2();
$subObject2_1=new SubObject2();
$o=$objectCollection->getObject($subObject1_1, $subObject2_1, 'hello'); //returns a new object
$o=$objectCollection->getObject($subObject1_2, $subObject2_1, 'hello'); //returns a new object
$o=$objectCollection->getObject($subObject1_1, $subObject2_1, 'goodby'); //returns a new object
$o=$objectCollection->getObject($subObject1_1, $subObject2_1, 'hello'); //returns existing object
这应该如何最好地实施?
一种可能性是类似于以下未经测试的代码,但是,它有点冗长,如果有更清洁的解决方案,我很感兴趣。
public function getObject(SubObject1 $subObject1, SubObject2 $subObject2, string $theString):MainObject {
if(isset($this->map[$theString])) {
if($this->map[$theString]->contains($subObject1)) {
$subObject1Storage=$this->map[$theString][$subObject1];
if($subObject1Storage->contains($subObject2)) {
$mainObject=$subObject1Storage[$subObject2];
}
else {
$mainObject=new MainObject($subObject1, $subObject2, $theString);
$subObject1Storage[$subObject2]=$mainObject;
}
}
else {
$subObject1Storage = new \SplObjectStorage();
$this->map[$theString][$subObject1]=$subObject1Storage;
$mainObject=new MainObject($subObject1, $subObject2, $theString);
$subObject1Storage[$subObject2]=$mainObject;
}
}
else {
$this->map[$theString] = new \SplObjectStorage();
$subObject1Storage = new \SplObjectStorage();
$this->map[$theString][$subObject1]=$subObject1Storage;
$mainObject=new MainObject($subObject1, $subObject2, $theString);
$subObject1Storage[$subObject2]=$mainObject;
}
return $mainObject;
}
【问题讨论】:
-
所以您正在寻找与各种工厂相结合的容器,还是我误解了这个?
-
@Andrew 是的,这是正确的。我应该在标签中包含
factory,然后添加它。 -
为什么不走久经考验的路线呢?为每个对象分配一个唯一的 id,将其转储到容器中,并在检索时使用“延迟加载”通过工厂生成新对象。长话短说,您可以传入任意数量的唯一标识符并即时创建它们。天啊,你甚至可以用反射做一些魔术来模拟基于创建的对象构造参数的递归对象创建。当然,这是矫枉过正,但它真的很干净。我想你也可以使用一些组件(想到 Symfony 的 DI)。如果你愿意,我可以给你一些写得不好的伪代码。
-
@Andrew 我认为您的想法是正确的。为每个人分配一个唯一的 ID。几乎
SplObjectStorage使用对象的哈希所做的事情。理想情况下,就我而言,它不是单个对象的拥有,而是两个对象加上字符串的拥有。您如何看待创建一个新类,该类的单一方法是一个构造函数,该构造函数保存两个对象加上字符串,并在 SplObjectStorage 中使用该对象?编辑。也许不是,因为它们是不同的实例...... -
所以你基本上想要一个不可变的哈希映射(或者一个希望在 php 世界中不会被修改的数组)?但是在您的情况下,它应该是 2 个对象的唯一哈希(我假设是连接的)以及您碰巧传入的任何字符串?这个好像有点臭。理想情况下,除非您有充分的理由不这样做,否则您希望将每个对象哈希分开,这允许您将来通过任何您想要的方式组合您想要的任何哈希。至于字符串本身,那就是另一回事了,我想你可以拥有任意数量的。
标签: php collections set factory splobjectstorage