我的问题适用于我为更好地理解如何使用 OOP 而编写的这三个示例类。
class Book {
//not using getters/setters to save some space
public $name;
public $numreads;
}
class BookFactory {
private $db;
public function __construct(Database $db) {
$this->db = $db;
}
public function getBook($id) {
$book = new Book();
$book->name = $db->query("SELECT name FROM books...");
$booknumreads = new BookNumRead($this->db, $book);
$book->numreads = $booknumreads->getFromLocal() + $booknumreads->getFromAnotherSource();
return $book;
}
}
class BookNumRead {
private $db;
private $book;
public function __construct(Database $db, Book $book) {
$this->db = $db;
$this->book = $book;
}
public function getFromLocal()
{
return $this->db->query("SELECT COUNT ... WHERE name = $book->name");
}
public function getFromAnotherSource()
{
return API::getNumReadsOfABook($book->name);
}
//or just stick with this method in this class
public function getNumReadsOfBook($name)
{
return (
$this->db->query("SELECT COUNT ... WHERE name = $name")
+
API::getNumReadsOfABook($name)
);
}
}
//get number of reads of a book
$db = new Database();
$bookfactory = new BookFactory($db);
$book = $bookfactory->getBook(123);
echo $book->getNumReads();
首先,这是一个好的 OOP 方法吗?
这些类是完全不同的。域与值对象?例如,我的应用程序中可以有我需要的尽可能多的 Book 对象。然而,BookFactory 就像我的应用程序中的一项服务,我的应用程序中只需要一个服务,但我可能需要我的应用程序中许多其他地方的这个类,我应该把它作为一个对象放在 ServiceLocator/ServiceContainer 中吗?
BookNumRead 类也可以放在 ServiceLocator/ServiceContainer 中,并由 getNumReadsOfBook() 方法使用,而无需注入 Book 对象,但这感觉像是过程编程?或者,就像上面的例子一样,由 BookFactory::getBook() 启动,但是我需要同时传递一个数据库(一个 BookFactory 被注入)和一个 Book 给它,这感觉有点混乱,因为它可能需要其他“服务”类,例如记录器。这里的最佳做法是什么?