OOP (beneficial usage)

前端 未结 3 921
南方客
南方客 2020-12-20 07:56

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 ARTICLE

相关标签:
3条回答
  • 2020-12-20 08:32

    First of all , in PHP5 the constructor it public function __construct(). What you are using there is the PHP4 way. And then ther eare other issues with your code:

    • instead of passing the name of the city to the Basket ( do you mean Cart ?), you should be creating the address object instance and passing it.
    • do not add items based on name an amount of money to the basket, instead add the whole instance of item, otherwise you will have a lot of problems when switching site language or currency.
    • the Articles (do you mean Items ?) should be created based on ID, not based on name. The reasons for that are the same as above + you will have issues with uniqueness. And then some of items might have lower price, when bought in combination. You need a way to safely identify them.

    As for cleaning up the code there:

    • you should stop creating instance from given parameters in the constructor. While it is not always a bad thing, in your case you are making a mess there.
    • Bill should not be responsible for printing itself.

    Something like :

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

    .. then use it as

    $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 );
    

    This would give you an instance of Bill outside the class which then you can either print or send to someone.

    Also , you might benefit from watching the willowing lecture:

    • Inheritance, Polymorphism, & Testing
    • Don't Look For Things!
    • Clean Code I: Arguments
    0 讨论(0)
  • 2020-12-20 08:43

    Both basket as well as bill could have a relation to a positions item - an object representing an ordered list of zero or more items with a count and price.

    As such a list is an object of it's own it's easy to pass around:

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

    However the printing of the bill should be done by the BillPrinter, because it's not the job of the bill to print itself:

    $billPrinter = new BillPrinter($bill, $printerDevice);
    $billPrinter->print();
    
    0 讨论(0)
  • 2020-12-20 08:45

    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.

    0 讨论(0)
提交回复
热议问题