5

私の質問は、OOP の使用方法をよりよく理解するために作成した 3 つのサンプル クラスに当てはまります。

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 はアプリケーションのサービスのようなものです。アプリケーションに必要なのは 1 つだけですが、アプリケーションの他の多くの場所からこのクラスが必要になる場合があります。ServiceLocator/ServiceContainer にオブジェクトとして配置する必要がありますか?

  3. BookNumRead クラスを ServiceLocator/ServiceContainer に配置して、Book オブジェクトを挿入せずに getNumReadsOfBook() メソッドで使用することもできますが、それは手続き型プログラミングのように感じますか? または、上記の例のように BookFactory::getBook() によって開始されますが、データベース (1 つの BookFactory が注入されたもの) と Book の両方をデータベースに渡す必要があります。たとえば、ロガーなどの他の「サービス」クラスが必要になる場合があります。ここでのベストプラクティスは何ですか?

4

2 に答える 2

1

モデル/サービスからDBのものをもっと分離する必要があると思います。DB スタッフにアダプター パターンを使用し、すべての 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 に答える