为了描述我的问题,我将使用某种更易于分析的类比,并且我认为这很好地反映了我的问题。
假设有一个 Library 类,它包含两个列表:书籍和书架。在 PHP 中,这两个列表最容易实现为数组,我这样做了——我在类库中创建了两个公共字段:书籍和书架,并在构造函数中用数组初始化它们。
class Library
{
public $books;
public $bookshelves;
public function __construct () {
$this->books = array();
$this->bookshelves = array();
}
}
一切都会好的,因为在数组中实现的方法就足够了。但是从编程最佳实践的角度来看,这段代码对我来说似乎不正确。我认为这门课不是那么封闭,是吗?有必要记住该字段的用途以及如何对待他。例如,如果我想将这本书添加到图书馆,我会在 Library 类中搜索方法 addBook。我从来没有想过我必须在图书馆类的外业手册上执行方法添加。
因此,我应该将书籍和书架作为私有字段,并在图书馆类中实现 addBook/addBookshelf、removeBook/removeBookshelf、getBook/getBookshelf 等功能。
class Library
{
private $books;
private $bookshelves;
public function __construct () {
$this->books = array();
$this->bookshelves = array();
}
public function addBook (Book $book) {
$this->books[] = $book;
}
public function removeBook ($id) {
$this->books[$id] = [];
}
public function getBook ($id) {
return $this->books[$id];
}
public function addBookhelf (Book $book) {
$this->bookshelf[] = $book;
}
public function removeBookhelf ($id) {
$this->bookshelf[$id] = [];
}
public function getBookhelf ($id) {
return $this->bookshelf[$id];
}
}
但这也是不正确的。为什么有人会花时间第二次编写已经在数组中实现的相同内容?一类,一项责任的原则是什么?
第三种方法是创建两个类:BooksList 和 BookshelvesList,它们扩展了 ArrayObject 类。他们没有任何额外的方法或字段。
class BooksList extends ArrayObject
{
}
class BookshelvesList extends ArrayObject
{
}
接下来,我应该用这个类初始化公共领域的书籍和书架。
class Library
{
private $books;
private $bookshelves;
public function __construct ()
{
$this->books = new BooksList();
$this->bookshelves = new BookshelvesList();
}
}
然后图书馆类不负责对书籍和书架的操作。并且没有第二次编写数组操作。但是正在创建两个没有添加新内容的奇怪对象。
所以我发明了三种实现我的问题的可能性,但每一种都有一些缺陷。这不是一些复杂的关系,它会是一种简单而优雅的实现方式。我寻找了一些适合这个问题的设计模式,但我没有找到。因此我在这里问,如何正确实施?