为了描述我的问题,我会使用一些比较简单的分析,我认为很好地反映了我的问题。
我们假设有一个Library类,其中包含两个列表:书籍和书架。在PHP这两个列表中,它最容易实现为数组,我这样做了 - 我在类库中创建了两个公共字段:书籍和书架,在构造函数中我用数组初始化它们。
class Library
{
public $books;
public $bookshelves;
public function __construct () {
$this->books = array();
$this->bookshelves = array();
}
}
一切都会好的,因为在数组中实现的方法就足够了。但从编程最佳实践的角度来看,这段代码对我来说似乎不对。我觉得这堂课不是那么密不透风,是吗?有必要记住该领域的用途以及如何对待他。例如,如果我想将书添加到库中,我会在库类中搜索方法addBook。我从来没有想过我必须在图书馆班的实地书上执行方法添加。
因此我应该将字段书和书架作为私有,并在Library类中实现函数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();
}
}
然后,图书馆课程不对书籍和书架上的操作负责。并且第二次没有写入数组操作。但是创造了两个奇怪的物体,它们并没有添加新东西。
所以我发明了实现我的问题的三种可能性,但每种都有一些缺陷。它不是一些复杂的关系,它将是一种简单而优雅的方式来实现它。我找了一些适合这个问题的设计模式,但我没找到。因此,我在这里问,如何正确实现这一点?
答案 0 :(得分:2)
只是提出你的一个问题:
为什么有人会花时间写第二次同样已经在数组中实现的内容?
如果你只是原型制作或者你可能不会做的事情。但大多数情况下,最好能够控制对对象中关键数据的访问。它可以保护您免受以后滥用的代码的影响(有人将Tree
对象直接添加到您的$books
数组中 - 您可以在addBook
函数中添加验证以轻松防止这种情况发生。其次,它为您提供了更多的灵活性。如果客户突然决定每次将书籍添加到图书集中时都希望向图书管理员发送电子邮件,该怎么办?如果您允许代码直接从任何地方添加公共变量,那么您可能需要先完成维护工作!