Сложный шаблон, почему это плохо, если «дети» знать о & quot; родителе & quot ;?

примеры кода: https://sourcemaking.com/design_patterns/composite/php Я сделал нечто подобное, кроме этогоOnTheBookShelf«знает около $ книг (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

Решение

Они должны знать об их интерфейсах, чтобы их можно было изменить.

Допустим, у вас есть классы:

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

Другие решения

Мои «начальники» говорят, что плохо, что они знают друг о друге. Но почему?

Проблема круговой ссылки между Shelf а также Book это не так тривиально и требует особой осторожности в работе.

Например, если вы просто напишите $oneBook->shelf = $this; внутри addBook метод, то что произойдет, если потребитель вызывает этот метод для одной книги на двух разных полках?

$book = new Book;
$shelf1 = new Shelf;
$shelf2 = new Shelf;

$shelf1->addBook($book);
$shelf2->addBook($book);

Book будет добавлен к обеим полкам, но он будет содержать ссылку только на последнюю полку, что приводит к несогласованности и потенциальным ошибкам во время выполнения.

Конечно, круговая ссылка может быть сделана правильно, но это требует особого внимания и усложняет код.

1