Gần đây tôi đã bắt đầu đọc về tiêm phụ thuộc và nó đã làm cho tôi suy nghĩ lại một số thiết kế của tôi.PHP Tải các đối tượng lười biếng và tiêm phụ thuộc
Sự cố tôi gặp phải là: Giả sử tôi có hai lớp: Xe hơi và Hành khách; Đối với những hai lớp tôi có một số người vẽ bản đồ dữ liệu để làm việc với cơ sở dữ liệu: CarDataMapper và PassengerDataMapper
Tôi muốn để có thể làm điều gì đó như thế này trong mã:
$car = CarDataMapper->getCarById(23); // returns the car object
foreach($car->getPassengers() as $passenger){ // returns all passengers of that car
$passenger->doSomething();
}
Trước khi tôi biết bất cứ điều gì về DI, tôi sẽ xây dựng các lớp học của tôi như thế này:
class Car {
private $_id;
private $_passengers = null;
public function getPassengers(){
if($this->_passengers === null){
$passengerDataMapper = new PassengerDataMapper;
$passengers = $passengerDataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
tôi cũng sẽ có mã tương tự như trong phương pháp Passenger-> getCar() để lấy xe chở khách là trong
.Bây giờ tôi hiểu rằng điều này tạo ra các phụ thuộc (tốt, tôi đã hiểu nó trước đây, nhưng tôi không biết rằng điều này là "sai") giữa các đối tượng Xe và Hành khách và các đối tượng bản đồ dữ liệu.
Trong khi cố gắng để nghĩ ra giải pháp cho hai lựa chọn này xuất hiện trong đầu, nhưng tôi không thực sự thích ai trong số họ:
1: Làm một cái gì đó như thế này:
$car = $carDataMapper->getCarById(23);
$passengers = $passengerDataMapper->getPassengersByCarId($car->getId());
$car->setPassengers($passengers);
foreach($car->getPassengers() as $passenger){
$passenger->doSomething();
}
Nhưng những gì nếu hành khách có đồ vật mà họ cần tiêm, và điều gì sẽ xảy ra nếu việc lồng nhau lên đến mười hoặc hai mươi cấp ... Tôi sẽ khởi động gần như mọi đối tượng trong phần đầu của ứng dụng, điều này sẽ lần lượt truy vấn toàn bộ cơ sở dữ liệu trong suốt quá trình. Nếu tôi phải gửi hành khách đến một đối tượng khác mà phải làm điều gì đó với các đối tượng mà hành khách nắm giữ, tôi cũng không muốn ngay lập tức khởi tạo các vật thể này.
2: Chích người vẽ bản đồ dữ liệu vào xe và hành khách đối tượng và có một cái gì đó như thế này:
class Car {
private $_id;
private $_passengers = null;
private $_dataMapper = null;
public function __construct($dataMapper){
$this->setDataMapper($dataMapper);
}
public function getPassengers(){
if($this->_passengers === null && $this->_dataMapper instanceof PassengerDataMapper){
$passengers = $this->_dataMapper->getPassengersByCarId($this->getId());
$this->setPassengers($passengers);
}
return $this->_passengers;
}
}
Tôi không giống như bất kỳ này tốt hơn, bởi vì nó không giống như các xe thực sự không biết gì về các mapper dữ liệu, và không có người lập bản đồ dữ liệu, Ô tô có thể hoạt động không thể đoán trước (không phải trả lại hành khách, khi thực sự có chúng)
Vì vậy, câu hỏi đầu tiên của tôi là: Tôi có một cách tiếp cận hoàn toàn sai ở đây, bởi vì, tôi càng nhìn vào nó , có vẻ như tôi đang xây dựng một ORM, thay vì một lớp kinh doanh?
Câu hỏi thứ hai là: có cách nào thực sự tách các đối tượng và trình ánh xạ dữ liệu theo cách cho phép tôi sử dụng các đối tượng như được mô tả trong khối mã đầu tiên không?
Thứ ba câu hỏi: Tôi đã nhìn thấy một số câu trả lời cho các ngôn ngữ khác (một số phiên bản của C, tôi nghĩ) giải quyết vấn đề này với một cái gì đó như thế này được mô tả ở đây: What is the proper way to inject a data access dependency for lazy loading? Như tôi đã không có thời gian để chơi với khác ngôn ngữ, điều này không có ý nghĩa với tôi, vì vậy tôi sẽ biết ơn nếu ai đó giải thích các ví dụ trong liên kết trong PHP-ish.Tôi cũng đã xem xét một số khuôn khổ DI và đọc về DI Containers và Inversion of Control, nhưng từ những gì tôi hiểu chúng được sử dụng để xác định và tiêm phụ thuộc cho các lớp 'không động', ví dụ, Ô tô sẽ phụ thuộc vào Engine, nhưng nó sẽ không cần động cơ được nạp động từ db, nó sẽ đơn giản được khởi tạo và tiêm vào trong xe.
Xin lỗi vì bài đăng dài và cảm ơn trước.
Bạn có thể muốn thanh toán [PoEAA] (http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?ie=UTF8&qid=1350785602&sr=8-1&keywords= mẫu + của + doanh nghiệp + ứng dụng + kiến trúc) Mặc dù nó sẽ không giúp ích gì cả với [DI] (http://martinfowler.com/articles/injection.html) (nó có trước sự phổ biến), bạn sẽ nhận ra rằng ngay cả với Business Layer bạn sẽ cần một ORM nằm dưới nó. Bạn nên sử dụng [Data Mapper] (http://martinfowler.com/eaaCatalog/dataMapper.html). 1 để đặt câu hỏi tôi đã tìm kiếm câu trả lời. – xenoterracide
Cảm ơn mẹo.Gần đây tôi đã sử dụng Doctrine2 trong hầu hết các dự án của tôi, đó là một ORM Mapper dữ liệu và trở nên khá dễ làm việc. – Pinetree