5

我的问题适用于我为更好地理解如何使用 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();
  1. 首先,这是一个好的 OOP 方法吗?

  2. 这些类是完全不同的。域与值对象?例如,我的应用程序中可以有我需要的尽可能多的 Book 对象。然而,BookFactory 就像我的应用程序中的一项服务,我的应用程序中只需要一个服务,但我可能需要我的应用程序中许多其他地方的这个类,我应该把它作为一个对象放在 ServiceLocator/ServiceContainer 中吗?

  3. BookNumRead 类也可以放在 ServiceLocator/ServiceContainer 中,并由 getNumReadsOfBook() 方法使用,而无需注入 Book 对象,但这感觉像是过程编程?或者,就像上面的例子一样,由 BookFactory::getBook() 启动,但是我需要同时传递一个数据库(一个 BookFactory 被注入)和一个 Book 给它,这感觉有点混乱,因为它可能需要其他“服务”类,例如记录器。这里的最佳做法是什么?

4

2 回答 2

1

我认为您应该将数据库内容更多地与模型/服务分开。对数据库内容使用适配器模式,并在单独的类中处理所有 SQL。您可以使适配器实现 PDO、MySQLi 等。

在更高、更实用的模型和服务层次上思考,并将实现细节隐藏在底层的通用类中。

于 2012-09-14T11:35:49.447 回答
0

我会考虑让 BookNumRead 成为 Book 的属性。

此外,在__construct()Book 的功能中,您可以考虑运行查询以获取所有书籍详细信息。

如果你改变:

class Book {
    //not using getters/setters to save some space
    public $name;
    public $numreads;
}

至:

class Book {
    //not using getters/setters to save some space
    public $name;
    public $numreads;

    public function __construct($id)
    {
        $this->db->query("SELECT COUNT ... WHERE name = $book->name");
        // Use return value to get number of times book is read...
        $this->numreads=$countFromDatabase;
    }
}

然后你可以创建一个= new Book($id);,你会自动得到它被读取的次数。

基于此,您还可以根据 ID 自动从数据库中获取名称(以及任何其他重要详细信息)

于 2012-09-14T11:38:15.580 回答