1

我正在尝试解决我的 PHP 代码中的一个问题,但这也是我在其他代码中也无法解决的问题。

我有一个必须属于一个且仅一个集合的对象。我将主要从集合的角度访问这些对象。如果不通过集合,其他代码不会被期望找到对象。

所以,我过去处理这个问题的方式是给对象一个对集合的引用。通过这种方式,我们尝试满足 Object 只能属于一个 Collection。然后我会将对象添加到集合中。

public function __construct(Collection $c)
{
    $this->setCollection($c);
}

public setCollection(Collection $c)
{
    $this->collection = $c;
    $c->addObject($this);
}

这与“不要重复自己”是一个明显的矛盾。之所以出现,是因为需要轻松访问对象集合和要求对象仅属于一个集合的要求彼此不一致。对象知道它在集合中,而集合知道对象在集合中。如果其中任何一个不同步,系统就会损坏。

当您开始尝试编写代码以将对象从一个集合移动到另一个集合时,问题就变得很明显了。或者在删除对象时。

那么,有没有人找到解决此类问题的方法?有什么我应该尝试的吗?最后,我可以通过大量的双重检查使其工作,但似乎必须有更好的方法。

4

1 回答 1

1

我不确定我是否遵循您的推理路线来完成“双重检查”的最终游戏......但是这样的代码有什么问题?

class Collection {

   public function AddMember(Member $m) {
       $m->SetCollection($this);
       // add to underlying data structure
   }

   public function RemoveMember(Member $m) {
       // remove from underlying data structure
   }
}

class Member {
    private $collection = null;

    public function SetCollection(Collection $c) {
        if($this->collection)
            $this->collection->RemoveMember($this);
        $this->collection = $c;
    }

    public __destruct() {
        if($this->collection)
            $this->collection->RemoveMember($this);
    }
}

语法可能已关闭,将其视为伪代码,未经测试,在需要时使用引用,其他免责声明等。

这是一个很棒的设计模式,其中友元类/方法对于适当的封装很有用,以防止集合对象以外的任何人设置或删除其集合中的成员。您还需要仔细考虑将哪些方法用作入口点,并在这些情况下做正确的事情,而不会陷入递归循环。对于这样的框架/库类,单元测试将使您的生活更轻松。

是的,我可以看到您可能担心if在基本上做任何添加、删除或销毁操作之前必须进行检查。但这就是智能且安全的指针/引用模式的本质。DRY 原则与其说是避免安全检查的冗余,不如说是避免拥有多个数据副本或算法的冗余实现。是的,我的伪代码中的每一个方法在技术上都是一种算法,但这里有一些东西需要细细琢磨(好吧,它们真的是一样的东西,从不同的角度说):

  1. 它们以恒定的时间运行(前提是您避免了我提到的递归陷阱)。
  2. 说真的:有史以来最短的算法。
  3. 如果您担心优化if库中一半的语句,那么您就错过了(单个)树的森林。优化时间最好花在使代码更易于使用、更易于维护和降低算法的复杂性上。它不会比恒定时间算法更复杂。
  4. 您不会通过if在每次添加或删除时执行额外的语句来固定您的处理器。您可以通过O(n^2)在大型n.

总而言之,没有更好的方法来实现安全的双链接数据结构。您必须检查每个链接的安全性,这就是它的方式。

于 2013-05-02T21:03:53.040 回答