Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
877 views
in Technique[技术] by (71.8m points)

php - OOP (beneficial usage)

for my question on how to use OOP in a beneficial way I assume as an example a BASKET to which its owner (Tom) having a certain ADDRESS (NY) can add ARTICLES (Bike, Car). Finally a BILL is printed containg all these information.

My problem is: How to handle collecting the information desired (here: owner, city, amount of items) from several objects? Because I think it is stupid to do this manually as done below (see 4.), isn't it? (even more since the amount of information increases in reality)

So what is the "clean way" for creating the bill / collecting the information needed in this example?

<?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.";
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you do Tell Dont Ask, you would indeed add a render method to the bill to which you would pass an instance of BillRenderer. Bill would then tell BillRenderer how to render the Bill. This is in accordance with InformationExpert and High Cohesion principles that suggest methods to be on the objects with the most information to fulfill the task.

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

BillRenderer (an interface) would then know the output format, e.g. you'd write concrete renderers for PlainText or HTML or PDF:

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

echo $bill->renderAs(new TxtBillRenderer);

If your Bill contains other objects, those would implement a renderAs method as well. The Bill would then pass the renderer down to these objects.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...