Your SlideShare is downloading. ×
Patterns in PHP
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Patterns in PHP

667

Published on

Software patterns in PHP

Software patterns in PHP

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
667
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
12
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Patterns: - Decorator . - Composite. Diego Lewin Senior Developer at Netconcepts
  • 2. Structural Patterns are Design Patterns that ease the design by identifying a simple way to realize relationships between entities. * Adapter pattern. * Aggregate pattern. * Bridge pattern. * Composite pattern. * Decorator pattern. * Extensibility pattern. * Facade pattern. * Flyweight pattern. * Proxy pattern. * Pipes and filters. * Private class data pattern. Structural Patterns
  • 3. The Decorator Pattern
    • The decorator pattern provides us with a mechanism for adding functionality to objects at runtime, as an alternative mechanism to creating additional child classes.
  • 4. The Problem
    • As an example we can use an E-comerce system, we have different modules like:
      • Related content (for products,categories,etc).
      • Customer Reviews (for products)..
      • Tag Clouds (for products,categories,etc)..
      • MYOB integration (for products)..
      • Custom functionality from a specific client, that we don't want to have in the core classes.
  • 5. The ”Classes” get_price()‏ is_available()‏ Product Customer_Review get_custom_reviews()‏ Tag_Cloud get_arr_tag_cloud()‏ Integration_MYOB do_integration()‏ Custom_Funtionality is_available()‏
  • 6. Customer_Review Tag_Cloud Custom_Funtionality Integration_MYOB get_custom_reviews()‏ get_arr_tag_cloud()‏ do_integration()‏ get_price()‏ is_available()‏ is_available()‏ How many extensions are TOO many? Product
  • 7. class Product { public function get_price(); public function is_available(); } class Integration_MYOB extends Product { public function do_integration()‏ { ....... } ......... } class Tag_Cloud extends Integration_MYOB { public function get_arr_tag_cloud()‏ { ....... } ......... } Some Code...
  • 8. class Customer_Review extends Tag_Cloud { public function get_arr_customer_review()‏ { ....... } ......... } class Custom_Functionality extends Customer_Review { public function is_available()‏ { ....... } ......... } More Code....
  • 9. Product Customer_Review Tag_Cloud Custom_Funtionality Integration_MYOB get_custom_reviews()‏ get_arr_tag_cloud()‏ do_integration()‏ do_integration()‏ is_available()‏ is_available()‏ Category But, not all the projects need the same functionality... I need to change my Code.., Class EXPLOSION
  • 10. Customer_Review_For_Product get_arr_custom_review()‏ Category Product do_integration()‏ is_available()‏ Customer_Review_For_Category get_arr_custom_review()‏ Tag_Cloud_For_Product get_arr_tag_cloud()‏ Tag_Cloud_For_Category get_arr_tag_cloud()‏ Even, there is more... I should reuse my extended classes !! get_arr_product()‏
  • 11. What, if we ”extend” the class in a 'run time' dynamically. Magic !! Example : /* *instantiation * we pass in the constructor, the object that we want to extend.. (decorate)‏ */ $obj_decorated_product = new Customer_Review(new Custom_Functionality( new Product)); /* * calling 'decorated' methods, the final reslut is the same as we extend the classes */ $arr_custom_review = $obj_decorated_product->get_arr_custom_review(); $is_available = $obj_decorated_product->is_available(); The Decorator comes to save us !
  • 12. Example 2: //instantiation, with 4 decoratros $obj_decorated_product = new Integration_MYOB( new Tag_Cloud( new Customer_Review(new Custom_Functionality( new Product)))); //calling 'decorated' methods $arr_custom_review = $obj_decorated_product->get_arr_custom_review(); $is_available = $obj_decorated_product->is_available(); $arr_tag_cloud = $obj_decorated_product->get_arr_tag_cloud(); Example 3: //instantiation, 'decorating' a product object and a category object with the same 'decorators' $obj_decorated_product = new Tag_Cloud( new Customer_Review( new Product)); $obj_decorated_category = new Tag_Cloud( new Customer_Review( new Category)); More Examples !
  • 13. //All the decorators have to extend the Abstract_Decorator class class Customer_Review_Decorator extends Abstract_Decorator { public function get_arr_customer_review()‏ { //insted of using parent:: , we need to use $this->object_decorated $entity_id = $this->object_decorated->id; ............ ............ return ......; } } class Custom_Functionality_Decorator extends Abstract_Decorator { public function is_available()‏ { //insted of using parent:: , we need to use $this->object_decorated $is_available = $this->object_decorated->is_available(); ............ ............ return ......; } } Concrete Decorators
  • 14. Customer_Review Tag_Cloud Custom_Funtionality Integration_MYOB get_custom_reviews()‏ get_arr_tag_cloud()‏ do_integration()‏ is_available()‏ __call()‏ __get()‏ __set()‏ UML Diagram (PHP 5 !)‏ obj_decorated Product get_price()‏ is_available()‏ Decorator
  • 15. abstract class Abstract_Decorator { /** * It is the object that we are decorating * and we must set it in the contructor */ protected $obj_decorated; public function __construct( $obj_decorated )‏ { $this->obj_decorated = $obj_decorated; } /** * If a function is not found in this class the call * came here and we forward to the $this->obj_decorated object */ protected function __call($method,$arguments)‏ { return call_user_func_array(array(&$this->obj_decorated, $method),$arguments); } /** * If a parameter that we are trying to read is not found in this class the call * came here and we forward to the $this->obj_decorated object */ protected function __get($property_name)‏ { return $this->obj_decorated->$property_name; } /** * If a parameter that we are tring to write is not found in this class the call * came here and we forward to the $this->obj_decorated object */ protected function __set($property_name, $property_value)‏ { return $this->obj_decorated->$property_name = $property_value; }
  • 16. get_price()‏ is_available()‏ discount_brand get_amount()‏ discount_category get_amount()‏ discount_buy_get get_amount()‏ discount_highest_price get_amount()‏ discount_custom get_amount()‏ Product
  • 17. Refactoring Diary Composite Pattern
  • 18. Discount calculations. Class Product { public function get_price()‏ { $price =... //now we apply the discounts $obj_discount_brand = new Discount_Brand($this->id,$qty); $price -= $obj_discount_brand->get_brand_discount(); $obj_discount_category = new Discount_Category(); $obj_discount_category->set_product_id($this->id); $obj_discount_category->set_qty($qty); $price -= $obj_discount_category->get_discount(); $obj_discount_highest_price = new Discount_Highest_Price($this->id,$qty); $price -= $obj_discount_category->get_amount(); $obj_discount_buy_get = new Discount_Buy_Get; $obj_discount_custom1 = new Discount_Custom1; $obj_discount_custom1 = new Discount_Customer_Big_Clients_EEUU; $obj_discount_custom1 = new Discount_Customer_EEUU; $obj_discount_custom1 = new Discount_Customer_NZ; return $price; } }
  • 19. Class Product { public function get_price() { $price =... //now we apply the discounts $obj_discount_brand = new Discount_Brand(); $obj_discount_brand->set_product_id($this->id)‏ $obj_discount_brand->set_qty($this->qty)‏ $price -= $obj_discount_brand->get_amount(); $obj_discount_category = new Discount_Category(); $obj_discount_category->set_product_id($this->id)‏ $obj_discount_category->set_qty($this->qty)‏ $price -= $obj_discount_category->get_amount(); $obj_discount_highest_price = new Discount_Highest_Price(); ............ ............... ............. return $price; } } A Commun Interface for the Discount classes and..what if the discounts have a commun interface...
  • 20.
    • But, if we have different discounts stategies for different projects, we need to update
    • our Product class.
    • Our Product class should be the same for all projects.
    • It should be ”Open for extension, but closed for modification”
    • And which is the primary responsability of the Product class ? Is discount calculations one of these responsabilities? (One responsability Rule).
    Open for extension, but closed for modification
  • 21. Class Product { public function get_price()‏ { $price =...; $obj_discount = new Discount_Composite; $obj_discount->set_product_id($product->id); $obj_discount->set_qty($product->qty); $price -=$obj_discount->get_amount(); return $price } } We are still using the same interface for the discount class, that we were using for each strategy: ->set_product_id($id)‏ ->set_qty(qty)‏ ->get_amount()‏ The new 'stable' Product class Decoupling the Discount from the Product class
  • 22. Decoupling the Discount from the Product class class Discount { public function __constructor( )‏ { $this->_arr_obj_discount_strategy array(new Discount_ Brand,new Discount_Category, new...)‏ } public function set_id ($id)‏ { foreach($this->_arr_obj_discount_strategy as &$obj_discount_strategy)‏ { $obj_discount_strategy->set_id ($id); } } public function set_qty ($qty)‏ { foreach($this->_arr_obj_discount_strategy as &$obj_discount_strategy)‏ { $obj_discount_strategy->set_qty ($qty); } } public function get_amount()‏ { foreach($this->_arr_obj_discount_strategy as $obj_discount_strategy)‏ { $amount += $obj_discount_strategy-> get_amount(); } return $amount; } }
  • 23. class Discount_Composite { public function add_strategy($obj_strategy)‏ { $this->_arr_obj_discount_strategy[]= $obj_strategy; } public function set_id($id)‏ { foreach($this->_arr_obj_discount_strategy as &$obj_discount_strategy)‏ { $obj_discount_strategy->set_id ($id); } } public function set_qty($qty)‏ { foreach($this->_arr_obj_discount_strategy as &$obj_discount_strategy)‏ { $obj_discount_strategy->set_qty ($qty); } } public function get_amount()‏ { foreach($this->_arr_obj_discount_strategy as $obj_discount_strategy)‏ { $amount += $obj_discount_strategy-> get_amount(); } return $amount; } } Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. [GoF, p163] The discount composite class
  • 24. Class Product_Controller { public function product()‏ { .................... .................... $obj_discount = new Discount_Composite $obj_discount->add_strategy(new Discount_Brand); $obj_discount->add_strategy(new Discount_Category); .................... .................... $obj_product->set_obj_discount($obj_discount); } } Class Product_Controller { public function product()‏ { .................... .................... $obj_discount = new Discount_Brand; .................... .................... $obj_product->set_obj_discount($obj_discount); } }
  • 25. Class Product_Controller { public function product()‏ { .................... .................... $obj_discount_composite = new Discount_Composite $obj_discount_composite->add_strategy( new Discount_Brand); $obj_discount_composite->add_strategy( newDiscount_Category); .................... .................... if(is_object($obj_customer))‏ { $obj_discount_composite_customer = new Discount_Composite $obj_discount_composite_customer->add_strategy('Discount_Seniors'); $obj_discount_composite_customer->add_strategy('Discount_Students'); } $obj_discount_composite->add_strategy($obj_discount_composite_customer); $obj_discount_composite->get_amount($obj_product ->get_id(),$obj_product ->get_qty()); } }
  • 26. Discount_Interface set_product_id()‏ set_qty()‏ get_amount()‏ Discount_Composite add_strategy()‏ remove_strategy()‏ Concrete_Discount Compose objects into tree structures to represent whole-part hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. [GoF, p163]
  • 27.
    • But, if we have different discounts stategies for different projects, we need to update
    • our Product class.
    • Or if a client ask for a different discount strategy, and they want to apply the
    • highest discount only, again, we need to update the Product class;
    • Our Product class should be the same for our all projects.
    • It should be ”close to modification and open to extension”

×