复合模式,如果"孩子"了解"父母"?

时间:2016-07-08 07:35:39

标签: php composition

代码示例:https://sourcemaking.com/design_patterns/composite/php我做了类似的事情,除了" OnTheBookShelf"了解$ books(SeveralBooks)。我的老板"说他们彼此了解不好。但为什么呢?

好吧,我编辑它:

abstract class OnTheBookShelf {
    public $shelf; /////////////////////////////////////////////////
    abstract function getBookInfo($previousBook);
    abstract function getBookCount();
    abstract function setBookCount($new_count);
    abstract function addBook($oneBook);
    abstract function removeBook($oneBook);
}

class OneBook extends OnTheBookShelf {
    private $title;
    private $author;
    function __construct($title, $author) {
      $this->title = $title;
      $this->author = $author;
    }
    function getBookInfo($bookToGet) {
      if (1 == $bookToGet) {
        return $this->title." by ".$this->author;
      } else {
        return FALSE;
      }
    }
    function getBookCount() {
      return 1;
    }
    function setBookCount($newCount) {
      return FALSE;
    }
    function addBook($oneBook) {
      return FALSE;
    }
    function removeBook($oneBook) {
      return FALSE;
    }
}

class SeveralBooks extends OnTheBookShelf {
    private $oneBooks = array();
    private $bookCount;
    public function __construct() {
      $this->setBookCount(0);
    }
    public function getBookCount() {
      return $this->bookCount;
    }
    public function setBookCount($newCount) {
      $this->bookCount = $newCount;
    }
    public function getBookInfo($bookToGet) {   
      if ($bookToGet <= $this->bookCount) {
        return $this->oneBooks[$bookToGet]->getBookInfo(1);
      } else {
        return FALSE;
      }
    }
    public function addBook($oneBook) {
      $oneBook->shelf = $this; //////////////////////////////////////////////////
      $this->setBookCount($this->getBookCount() + 1);
      $this->oneBooks[$this->getBookCount()] = $oneBook;
      return $this->getBookCount();
    }
    public function removeBook($oneBook) {
      $counter = 0;
      while (++$counter <= $this->getBookCount()) {
        if ($oneBook->getBookInfo(1) == 
          $this->oneBooks[$counter]->getBookInfo(1)) {
          for ($x = $counter; $x < $this->getBookCount(); $x++) {
            $this->oneBooks[$x] = $this->oneBooks[$x + 1];
          }
          $this->setBookCount($this->getBookCount() - 1);
        }
      }
      return $this->getBookCount();
    }
}

我在问题界线上加了一堆////////////////。在这里,他们说这本书提到了货架。

2 个答案:

答案 0 :(得分:1)

他们应该知道他们的界面,以便他们可以改变。

假设您有课程:

Bookshelf
  private books: Book[]

Book
  public title: String

然后,您将访问books[i].title并显示图书的标题。

现在想象一下,负责Book的程序员决定标题是自己的类,所以我们有:

Book
  public title: Title

Title
  private t: String
  public toString()

现在编程Bookshelf的程序员需要更改代码。

另一方面,如果我们有:

Book
  private title: String
  public getTitleString()

然后我们可以改变Book类的实现,我们所要做的就是编写将返回标题字符串表示的getTitleString()函数,一切都将继续在Bookshelf没有任何其他更改的情况下工作。

答案 1 :(得分:1)

  

我的老板&#34;说他们彼此了解不好。但为什么呢?

问题是Book$oneBook->shelf = $this;之间的循环引用并非如此微不足道,需要特别小心才能使用。

例如,如果您只是在addBook方法中编写$book = new Book; $shelf1 = new Shelf; $shelf2 = new Shelf; $shelf1->addBook($book); $shelf2->addBook($book); ,那么如果消费者在两个不同的书架上为一本书调用此方法会发生什么?

Book

virtual将被添加到两个架子上,但它只能引用最后一个架子,这会导致不一致和潜在的运行时错误。

原因是,循环引用可以正确完成,但需要特别注意并增加代码的复杂性。