ООП (выгодное использование)

для моего вопроса о том, как использовать ООП выгодным образом, я предполагаю в качестве примера КОРЗИЮ, к которой ее владелец (Том), имеющий определенный ADDRESS (NY), может добавить СТАТЬИ (Bike, Car). Наконец, BILL печатается со всей информацией.

Моя проблема: как справиться с собиранием необходимой информации (здесь: владелец, город, количество предметов) из нескольких объектов? Потому что я думаю, что глупо делать это вручную, как показано ниже (см. 4.), не так ли? (тем более, что в действительности объем информации увеличивается)

Итак, что такое «чистый способ» для создания счета / сбора информации, необходимой в этом примере?

<?php $a = new basket('Tom','NY'); $a->add_item("Bike",1.99); $a->add_item("Car",2.99); $b = new bill( $a ); $b->do_print(); 

1.

 class basket { private $owner = ""; private $addr = ""; private $articles = array(); function basket( $name, $city ) { // Constructor $this->owner = $name; $this->addr = new addresse( $city ); } function add_item( $name, $price ) { $this->articles[] = new article( $name, $price ); } function item_count() { return count($this->articles); } function get_owner() { return $this->owner; } function get_addr() { return $this->addr; } } 

2.

 class addresse { private $city; function addresse( $city ) { // Constructor $this->city = $city; } function get_city() { return $this->city; } } 

3.

 class article { private $name = ""; private $price = ""; function article( $n, $p ) { // Constructor $this->name = $n; $this->price = $p; } } 

4.

 class bill { private $recipient = ""; private $city = ""; private $amount = ""; function bill( $basket_object ) { $this->recipient = $basket_object->get_owner(); $this->city = $basket_object->get_addr()->get_city(); $this->amount = $basket_object->item_count(); } function do_print () { echo "Bill for " . $this->recipient . " living in " . $this->city . " for a total of " . $this->amount . " Items."; } } 

Solutions Collecting From Web of "ООП (выгодное использование)"

Если вы скажете «Не задавать вопрос» , вы действительно добавите метод рендеринга в счет, которому вы передадите экземпляр BillRenderer. Затем Билл расскажет БиллРендеруру, как передать законопроект. Это соответствует принципам InformationExpert и High Cohesion, которые предлагают методы быть на объектах с наибольшей информацией для выполнения задачи.

 class Bill { … public function renderAs(BillRenderer $billRenderer) { $billRenderer->setRecipient($this->owner); $billRenderer->setAddress($this->address); … return $billRenderer->render(); } } 

Тогда BillRenderer (интерфейс) знает формат вывода, например, вы должны писать конкретные рендереры для PlainText или HTML или PDF:

 class TxtBillRenderer implements BillRenderer { … public function render() { return sprintf('Invoice for %s, %s', $this->name, $this->address); } } echo $bill->renderAs(new TxtBillRenderer); 

Если ваш Билл содержит другие объекты, они также будут внедрять метод renderAs. Билл затем передал рендер на эти объекты.

Как корзина, так и счет могут иметь отношение к элементу позиций – объект, представляющий упорядоченный список из нуля или более пунктов со счетом и ценой.

Поскольку такой список является объектом его собственного, его легко обойти:

 $bill = new Bill($buyer, $address, $basket->getPositions()); 

Однако печать законопроекта должна выполняться BillPrinter , потому что печать не должна выполняться самим документом:

 $billPrinter = new BillPrinter($bill, $printerDevice); $billPrinter->print(); 

Прежде всего, в PHP5 конструктор он public function __construct() . То, что вы используете, есть способ PHP4. И затем другие проблемы с вашим кодом:

  • вместо того, чтобы передавать название города в Basket (вы имеете в виду « Cart ?»), вы должны создать экземпляр объекта адреса и передать его.
  • не добавляйте в корзину предметы, основанные на имени, и не добавляйте весь экземпляр элемента, иначе у вас будет много проблем при переключении языка сайта или валюты.
  • Articles (вы имеете в виду Items ?) должны создаваться на основе идентификатора, а не на основе имени. Причины этого те же, что и выше +, у вас будут проблемы с уникальностью. И тогда некоторые предметы могут иметь более низкую цену при покупке в комбинации. Вам нужен способ безопасно идентифицировать их.

Что касается очистки кода там:

  • вы должны прекратить создание экземпляра из заданных параметров в конструкторе. Хотя это не всегда плохо, в вашем случае вы делаете беспорядок там.
  • Bill не должен нести ответственность за печать.

Что-то вроде :

 class Basket { // -- other code public function handleInvoice( Bill $invoice ) { $invoice->chargeFor( $this->items ); $invoice->chargeTo( $this->account ); return $invoice->process(); } } 

.. затем используйте его как

 $cart = new Basket(..); // some operation with it $invoice = new Bill; $cart->handleInvoice($invoice); $printer = new PDFPrinter; // OR new JpegPrinter; OR new FakePrinter OR anything else $printer->print( $invoice ); - $cart = new Basket(..); // some operation with it $invoice = new Bill; $cart->handleInvoice($invoice); $printer = new PDFPrinter; // OR new JpegPrinter; OR new FakePrinter OR anything else $printer->print( $invoice ); 

Это даст вам экземпляр Bill вне класса, который затем вы можете распечатать или отправить кому-то.

Кроме того, вам может быть полезно наблюдать за ивовой лекцией:

  • Наследование, полиморфизм и тестирование
  • Не смотрите на вещи!
  • Чистый код I: Аргументы