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

Head First Patterns in PHP

Head First Patterns in PHP

大澤木小鐵

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