wtorek, 12 lutego 2013

Refactoring To Command Pattern

//usage of command pattern to refactoring big or overloaded methods
//Gigantic classes with hard to change methods
class Wrong_Customer {
    var  $_age;
    var $_bill;
    var $_man;
    function __construct($age, $bill, $man) {
        $this->_age=$age;
        $this->_bill=$bill;
        $this->_man= $man;
    }
    //addind discount will require modyfy other classes
    //new calculation devices requre to chenge methods
    function returnFinalBill() {
        $discountPercent=0;
        if($this->_age >60) { $discountPercent +=0.10;}
        if(!$this->_man) { $discountPercent +=0.20;}
        $bill = $this->_bill*(1-$discountPercent);   //100%=1
        return ("Wrong Customer Bill Amount: $".$bill."
"); } } interface BillPlayer { //based on sex how to calculate bill public function calculateBill($amountDue); } interface Command { //methods that change function executeCalculateBill($amountDue); } class WomanOver60 implements BillPlayer { public function calculateBill($amountDue) { return "Bill Amount for Woman over 60: $".($amountDue*(1-0.30))."
"; } } class ManOver60 implements BillPLayer { public function calculateBill($amountDue) { return "Bill Amount for Man over 60: $".($amountDue*(1-0.10))."
"; } } class ManUnder60 implements BillPLayer { public function calculateBill($amountDue) { return "Bill Amount for Man under 60: $".($amountDue)."
"; //no discount } } class Waiter implements Command { //Comander var $_billPayer; function __construct(BillPlayer $billPayer) { $this->_billPayer=$billPayer; } function executeCalculateBill($amountDue) { return $this->_billPayer->calculateBill($amountDue); } } class CashRegister { //invoker from command pattern, execute diferent methods based onobject type passed //return final bill //_Waiter diferent weiters, !adds flexibility! //stores Command's var $_command; function __construct(Command $command) { $this->_command=$command; //all things that implements command //like waiters } function returnFinalBill($amountDue) { return $this->_command->executeCalculateBill($amountDue); } } // more flexebility - only one thing to change for adding bill Payers class CustomerTypePicker { //if u want NEW bill payer tpe goes here!!! static function getManOver60(){ return new ManOver60(); } static function getManUnder60(){ return new ManUnder60(); } static function getWomanOver60(){ return new WomanOver60(); } } //adding customer group for easier to menage diferent customers class CustomerGroup { private $_customers=array(); function __construct($customers=array()) { $this->_customers = $customers; } function getCustomer($index) { return $this->_customers[$index]; } function addCustomer(BillPlayer $customer) { return $this->_customers[]=$customer; }//TODO deleteCustomer } class Main { function __construct() { $wC = new Wrong_Customer(70, 100, false); //woman Over 60 echo $wC->returnFinalBill(); } function testCommandOnWomenOver60() { $picker = new CustomerTypePicker(); $sally = $picker::getWomanOver60(); $waiter = new Waiter($sally); //sallysWaiter $bill = new CashRegister($waiter); echo $bill->returnFinalBill(100); } function testCommandOnManOver60() { //NOW better groups customers to array $picker = new CustomerTypePicker(); $bob = $picker::getManOver60(); $waiter = new Waiter($bob); //sallysWaiter $bill = new CashRegister($waiter); echo $bill->returnFinalBill(100); } function testCustomerGroup() { $picker = new CustomerTypePicker(); $customerGroup = new CustomerGroup(); $sally = $picker::getWomanOver60(); $customerGroup->addCustomer($sally); echo $customerGroup->getCustomer(0)->calculateBill(100); } } $run = new Main(); $run->testCommandOnWomenOver60(); $run->testCommandOnManOver60(); $run->testCustomerGroup();
Java implementation here: http://www.newthinktank.com/2013/02/code-refactoring-13/

Brak komentarzy:

Prześlij komentarz