关于如何以有益的方式使用OOP的问题我假设一个BASKET,它的拥有者(Tom)有一个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.";
}
}
答案 0 :(得分:2)
如果您执行Tell Dont Ask,您确实会将一个呈现方法添加到您将传递BillRenderer实例的帐单中。比尔会告诉BillRenderer如何提交条例草案。这符合InformationExpert and High Cohesion principles,它建议使用最多信息来完成任务的对象。
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);
如果您的Bill包含其他对象,那么它们也会实现renderAs方法。然后,条例草案会将渲染器传递给这些物体。
答案 1 :(得分:1)
篮子和账单都可以与头寸项目有关系 - 一个对象代表零个或多个具有计数和价格的项目的有序列表。
因为这样的列表是它自己的一个对象,所以很容易传递:
$bill = new Bill($buyer, $address, $basket->getPositions());
然而,帐单的打印应该由BillPrinter
完成,因为打印本身不是账单的工作:
$billPrinter = new BillPrinter($bill, $printerDevice);
$billPrinter->print();
答案 2 :(得分:1)
首先,在PHP5中构造函数public function __construct()
。您使用的是PHP4方式。然后再解决您的代码中的其他问题:
Basket
(你的意思是Cart
吗?),你应该创建地址对象实例并传递它。 / LI>
Articles
(您的意思是Items
?)应该根据ID创建,而不是基于名称。原因与上述相同+您将遇到唯一性问题。然后,当组合购买时,一些物品可能具有较低的价格。您需要一种安全识别它们的方法。至于清理那里的代码:
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 );
这会在课外提供Bill
的实例,然后您可以打印或发送给某人。
此外,您可能会从观看柳叶讲座中受益: