Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Head First Patterns in PHP

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Head First Patterns in PHP

Avatar for 大澤木小鐵

大澤木小鐵

March 23, 2012
Tweet

More Decks by 大澤木小鐵

Other Decks in Programming

Transcript

  1. 在圖片上加上浮水印 // 從 JPEG 圖檔來建立影像資源 if ($image = imageCreateFromJpeg('input.jpg')) {

    // // ... 處理影像 ... // // 輸出成 JPEG 圖檔 imageJpeg($image, 'output.jpg', 100); imageDestroy($image); }
  2. 修改後的版本 // 改用抽象形式來建立影像資源 if ($image = Image::createFrom('input.jpg')) { // //

    ... 處理影像 ... // // 輸出成 JPEG 圖檔 $image->saveAs('output.jpg', 'jpeg'); }
  3. switch 版本 class Product { // ... public function __construct($sn,

    $price) { $this->_sn = $sn; switch (substr($this->_sn, 0, 1)) { case 'A': $this->_price = (int) $price * 0.8; break; case 'B': $this->_price = (int) $price - 10; break; default: $this->_price = (int) $price; break; } } // ... }
  4. class Cart { // ... public function addProduct($sn, $price) {

    $this->_products[$sn] = new Product($sn, $price); } // ... }
  5. Strategy Pattern 版本 class Product { // ... public function

    __construct($sn, $price, Promotion $promo) { $this->_sn = $sn; $this->_price = $promo->calculate($price); } // ... } interface Promotion { public function calculate($price); }
  6. class Promotion_20PercentOff implements Promotion { public function calculate($price) { return

    $price * 0.8; } } class Promotion_10DollarMinus implements Promotion { public function calculate($price) { return $price - 10; } } class Promotion_Default implements Promotion { public function calculate($price) { return $price; } }
  7. class Cart { // ... public function addProduct($sn, $price) {

    switch (substr($sn, 0, 1)) { case 'A': $promo = new Promotion_20PercentOff(); break; case 'B': $promo = new Promotion_10DollarMinus(); break; default: $promo = new Promotion_Default(); break; } $this->_products[$sn] = new Product($sn, $price, $promo); } // ... }
  8. Simple Factory 版本 class Cart { // ... protected function

    _getPromoMap() { return array( 'A' => 'Promotion_20PercentOff', 'B' => 'Promotion_10DollarMinus', '*' => 'Promotion_Default', ); } // ... }
  9. class Cart { // ... public function addProduct($sn, $price) {

    switch (substr($sn, 0, 1)) { case 'A': $promo = new Promotion_20PercentOff(); break; case 'B': $promo = new Promotion_10DollarMinus(); break; default: $promo = new Promotion_Default(); break; } $this->_products[$sn] = new Product($sn, $price, $promo); } // ... } 修改前
  10. class Cart { // ... public function addProduct($sn, $price) {

    $key = substr($sn, 0, 1); $promoMap = $this->_getPromoMap(); $promoName = array_key_exists($key, $promoMap) ? $promoMap[$key] // 決定促銷類別名稱 : $promoMap['*']; // 預設的促銷類別 $promo = new $promoName(); $this->_products[$sn] = new Product($sn, $price, $promo); } // ... } 修改後
  11. class Order { public function save() { if ($this->_insertDb()) {

    $this->_updateMemberInfo(); $this->_sendMailToShopper(); $this->_saveLog(); } else { $this->_rollback(); } } protected function _insertDb() { /* ... */ } protected function _sendMailToShopper() { /* ... */ } protected function _updateMemberInfo() { /* ... */ } protected function _saveLog() { /* ... */ } protected function _rollback() { /* ... */ } } $order = new Order(); $order->save(); 原始版本
  12. interface Subject { public function notify(); } class Order implements

    Subject { protected $_observers = array(); public function register(Observer $observer) { $this->_observers[] = $observer; } public function notify() { foreach ($this->_observers as $observer) { $observer->update($this); } } } Observer 版本
  13. class Order implements Subject { // ... public function save()

    { if ($this->_insertDb()) { $this->notify(); } else { $this->_rollback(); } } protected function _insertDb() { /* ... */ return true; } protected function _rollback() { /* ... */ } }
  14. interface Observer { public function update(Subject $subject); } class Mail

    implements Observer { public function update(Subject $subject) { /* ... */ } } class Member implements Observer { public function update(Subject $subject) { /* ... */ } } class Log implements Observer { public function update(Subject $subject) { /* ... */ } }
  15. interface Subject {} class Order implements Subject { public function

    on($event, Observer $observer) { if (!isset($this->_observers[$event])) { $this->_observers[$event] = array(); } $this->_observers[$event][] = $observer; return $this; } public function trigger($event) { foreach ($this->_observers[$event] as $observer) { $observer->update($this); } } } Event 版本
  16. class Order implements Subject { // ... public function save()

    { if ($this->_insertDb()) { $this->trigger("save"); } else { $this->trigger("error"); } } }
  17. class Rollback implements Observer { public function update(Subject $subject) {

    /* ... */ } } $order = new Order(); $order->on("save", new Member()) ->on("save", new Mail()) ->on("save", new Log()) ->on("error", new Rollback()) ->save();
  18. Single responsibility principle (單一責任原則) Open/closed principle (開放封閉原則) Liskov substitution principle

    (Liskov 代換原則) Interface segregation principle (介面分隔原則) Dependency inversion principle (依賴反轉原則) SOLID