php經常使用幾種設計模式的應用場景

1.單例設計模式

所謂單例模式,即在應用程序中最多隻有該類的一個實例存在,一旦建立,就會一直存在於內存中!

單例設計模式常應用於數據庫類設計,採用單例模式,只鏈接一次數據庫,防止打開多個數據庫鏈接。

一個單例類應具有如下特色:

單例類不能直接實例化建立,而是隻能由類自己實例化。所以,要得到這樣的限制效果,構造函數必須標記爲private,從而防止類被實例化。

須要一個私有靜態成員變量來保存類實例和公開一個能訪問到實例的公開靜態方法。

在PHP中,爲了防止他人對單例類實例克隆,一般還爲其提供一個空的私有__clone()方法。

單例模式的例子:php

<?php
  
/**
* Singleton of Database
*/
class Database
{
  // We need a static private variable to store a Database instance.
  privatestatic $instance;
  
  // Mark as private to prevent it from being instanced.
  private function__construct()
  {
    // Do nothing.
  }
  
  private function__clone() 
  {
    // Do nothing.
  }
  
  public static function getInstance() 
  {
    if (!(self::$instance instanceof self)) {
      self::$instance = new self();
    }
  
    return self::$instance;
  }
}
  
$a =Database::getInstance();
$b =Database::getInstance();
  
// true
var_dump($a === $b);

2.工廠設計模式
主要是當操做類的參數變化時,只用改相應的工廠類就能夠

工廠設計模式經常使用於根據輸入參數的不一樣或者應用程序配置的不一樣來建立一種專門用來實例化並返回其對應的類的實例。

咱們舉例子,假設矩形、圓都有一樣的一個方法,那麼咱們用基類提供的API來建立實例時,經過傳參數來自動建立對應的類的實例,他們都有獲取周長和麪積的功能。mysql

 <?php
      
    interface InterfaceShape
    {
     function getArea();
     function getCircumference();
    }
      
    /**
    * 矩形
    */
    class Rectangle implements InterfaceShape
    {
      private $width;
      private $height;
       
      public function __construct($width, $height)
      {
        $this->width = $width;
        $this->height = $height;
      }
      
      public function getArea()
      {
        return $this->width* $this->height;
      }
      
      public function getCircumference()
      {
        return 2 * $this->width + 2 * $this->height;
      }
    }
      
    /**
    * 圓形
    */
    class Circle implements InterfaceShape
    {
      private $radius;
      
      function __construct($radius)
      {
        $this->radius = $radius;
      }
      
      
      public function getArea()
      {
        return M_PI * pow($this->radius, 2);
      }
      
      public function getCircumference()
      {
        return 2 * M_PI * $this->radius;
      }
    }
      
    /**
    * 形狀工廠類
    */
    class FactoryShape
    {
      public static function create()
      {
        switch (func_num_args()) {
          case1:
          return newCircle(func_get_arg(0));
          case2:
          return newRectangle(func_get_arg(0), func_get_arg(1));
          default:
            # code...
            break;
        }
      }
    }
      
    $rect =FactoryShape::create(5, 5);
    // object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) }
    var_dump($rect);
    echo "<br>";
      
    // object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
    $circle =FactoryShape::create(4);
    var_dump($circle);

3.觀察者設計模式

觀察者模式是挺常見的一種設計模式,使用得當會給程序帶來很是大的便利,使用得不當,會給後來人一種難以維護的想法。

什麼是觀察者模式?一個對象經過提供方法容許另外一個對象即觀察者 註冊本身)使自己變得可觀察。當可觀察的對象更改時,它會將消息發送到已註冊的觀察者。這些觀察者使用該信息執行的操做與可觀察的對象無關。結果是對象能夠相互對話,而沒必要了解緣由。觀察者模式是一種事件系統,意味着這一模式容許某個類觀察另外一個類的狀態,當被觀察的類狀態發生改變的時候,觀察類能夠收到通知而且作出相應的動做;觀察者模式爲您提供了避免組件之間緊密耦。看下面例子你就明白了!git

 <?php
      
    /*
    觀察者接口
    */
    interface InterfaceObserver
    {
      function onListen($sender, $args);
      function getObserverName();
    }
      
    // 可被觀察者接口
    interface InterfaceObservable
    {
      function addObserver($observer);
      function removeObserver($observer_name);
    }
      
    // 觀察者抽象類
    abstract class Observer implements InterfaceObserver
    {
      protected $observer_name;
      
      function getObserverName()
      {
        return $this->observer_name;
      }
      
      function onListen($sender, $args)
      {
      
      }
    }
      
    // 可被觀察類
    abstract class Observable implements InterfaceObservable
    {
      protected $observers = array();
      
      public function addObserver($observer)
      {
        if ($observerinstanceofInterfaceObserver)
        {
          $this->observers[] = $observer;
        }
      }
      
      public function removeObserver($observer_name)
      {
        foreach ($this->observersas $index => $observer)
        {
          if ($observer->getObserverName() === $observer_name)
          {
            array_splice($this->observers, $index, 1);
            return;
          }
        }
      }
    }
      
    // 模擬一個能夠被觀察的類
    class A extends Observable
    {
      public function addListener($listener)
      {
        foreach ($this->observersas $observer)
        {
          $observer->onListen($this, $listener);
        }
      }
    }
      
    // 模擬一個觀察者類
    class B extends Observer
    {
      protected $observer_name = 'B';
      
      public function onListen($sender, $args)
      {
        var_dump($sender);
        echo "<br>";
        var_dump($args);
        echo "<br>";
      }
    }
      
    // 模擬另一個觀察者類
    class C extends Observer
    {
      protected $observer_name = 'C';
      
      public function onListen($sender, $args)
      {
        var_dump($sender);
        echo "<br>";
        var_dump($args);
        echo "<br>";
      }
    }
      
    $a = new A();
    // 注入觀察者
    $a->addObserver(new B());
    $a->addObserver(new C());
      
    // 能夠看到觀察到的信息
    $a->addListener('D');
      
    // 移除觀察者
    $a->removeObserver('B');
      
    // 打印的信息:
    // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
    // string(1) "D"
    // object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
    // string(1) "D"

4.適配器模式
將一個類的接口轉換成客戶但願的另外一個接口,適配器模式使得本來的因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。
應用場景:老代碼接口不適應新的接口需求,或者代碼不少很亂不便於繼續修改,或者使用第三方類庫。例如:php鏈接數據庫的方法:mysql,,mysqli,pdo,能夠用適配器統一github

  //老的代碼     
     
    class User {    
     
        private $name;    
     
        function __construct($name) {    
     
            $this->name = $name;    
     
        }    
     
        public function getName() {    
     
            return $this->name;    
     
        }    
     
    }   
    //新代碼,開放平臺標準接口    
     
    interface UserInterface {    
     
        function getUserName();    
     
    }    
     
    class UserInfo implements UserInterface {    
     
        protected $user;    
     
        function __construct($user) {    
     
            $this->user = $user;    
     
        }    
     
        public function getUserName() {    
     
            return $this->user->getName();    
     
        }    
     
    }   
    $olduser = new User('張三');    
     
    echo $olduser->getName()."n";    
     
    $newuser = new UserInfo($olduser);    
     
    echo $newuser->getUserName()."n";    

5.策略模式
將一組特定的行爲和算法封裝成類,以適應某些特定的上下文環境。
例如:一個電商網站系統,針對男性女性用戶要各自跳轉到不一樣的商品類目,而且全部廣告位展現不一樣的廣告算法

UserStrategy.php
<?php
     
    namespace IMooc;
     
     
    interface UserStrategy {
        function showAd();
        function showCategory();
    } 

MaleUserStrategy.phpsql

 <?php
     
    namespace IMooc;
     
     
    class MaleUserStrategy implements UserStrategy  {
     
        function showAd()
        {
            echo "IPhone6";
        }
     
        function showCategory()
        {
            echo "電子產品";
        }
    } 

FemaleUserStrategy.php數據庫

<?php
     
    namespace IMooc;
     
    class FemaleUserStrategy implements UserStrategy {
        function showAd()
        {
            echo "2014新款女裝";
        }
        function showCategory()
        {
            echo "女裝";
        }
    }
<?php
    interface FlyBehavior{
        public function fly();
    }
     
    class FlyWithWings implements FlyBehavior{
        public function fly(){
            echo "Fly With Wings \n";
        }
    }
     
    class FlyWithNo implements FlyBehavior{
        public function fly(){
            echo "Fly With No Wings \n";
        }
    }
    class Duck{
        private $_flyBehavior;
        public function performFly(){
            $this->_flyBehavior->fly();
        }
     
        public function setFlyBehavior(FlyBehavior $behavior){
            $this->_flyBehavior = $behavior;
        }
    }
     
    class RubberDuck extends Duck{
    }
    // Test Case
    $duck = new RubberDuck();
     
    /*  想讓鴨子用翅膀飛行 */
    $duck->setFlyBehavior(new FlyWithWings());
    $duck->performFly();            
     
    /*  想讓鴨子不用翅膀飛行 */
    $duck->setFlyBehavior(new FlyWithNo());
    $duck->performFly();

6.裝飾器模式
使用場景:當某一功能或方法draw,要知足不一樣的功能需求時,可使用裝飾器模式;實現方式:在方法的類中建addDecorator(添加裝飾器),beforeDraw,afterDraw 3個新方法, 後2個分別放置在要修改的方法draw首尾.而後建立不一樣的裝器類(其中要包含相同的,beforeDraw,afterDraw方法)能過addDecorator添加進去,而後在beforeDraw,afterDraw中循環處理,與觀察者模式使用有點類似
1.裝飾器模式(Decorator),能夠動態地添加修改類的功能
2.一個類提供了一項功能,若是要在修改並添加額外的功能,傳統的編程模式,須要寫一個子類繼承它,並從新實現類的方法
3.使用裝飾器模式,僅需在運行時添加一個裝飾器對象便可實現,能夠實現最大的靈活性
DrawDecorator.php編程

<?php
    namespace IMooc;
     
    interface DrawDecorator
    {
        function beforeDraw();
        function afterDraw();
    }

Canvas.php

    <?php
    namespace IMooc;
     
    class Canvas
    {
        public $data;
        protected $decorators = array();
     
        //Decorator
        function init($width = 20, $height = 10)
        {
            $data = array();
            for($i = 0; $i < $height; $i++)
            {
                for($j = 0; $j < $width; $j++)
                {
                    $data[$i][$j] = '*';
                }
            }
            $this->data = $data;
        }
     
        function addDecorator(DrawDecorator $decorator)
        {
            $this->decorators[] = $decorator;
        }
     
        function beforeDraw()
        {
            foreach($this->decorators as $decorator)
            {
                $decorator->beforeDraw();
            }
        }
     
        function afterDraw()
        {
            $decorators = array_reverse($this->decorators);
            foreach($decorators as $decorator)
            {
                $decorator->afterDraw();
            }
        }
     
        function draw()
        {
            $this->beforeDraw();
            foreach($this->data as $line)
            {
                foreach($line as $char)
                {
                    echo $char;
                }
                echo "<br />\n";
            }
            $this->afterDraw();
        }
     
        function rect($a1, $a2, $b1, $b2)
        {
            foreach($this->data as $k1 => $line)
            {
                if ($k1 < $a1 or $k1 > $a2) continue;
                foreach($line as $k2 => $char)
                {
                    if ($k2 < $b1 or $k2 > $b2) continue;
                    $this->data[$k1][$k2] = ' ';
                }
            }
        }
    }

ColorDrawDecorator.phpcanvas

  <?php
    namespace IMooc;
     
    class ColorDrawDecorator implements DrawDecorator
    {
        protected $color;
        function __construct($color = 'red')
        {
            $this->color = $color;
        }
        function beforeDraw()
        {
            echo "<div style='color: {$this->color};'>";
        }
        function afterDraw()
        {
            echo "</div>";
        }
    }

index.php設計模式

  <?php
    define('BASEDIR', __DIR__);
    include BASEDIR.'/IMooc/Loader.php';
    spl_autoload_register('\\IMooc\\Loader::autoload');
     
    $canvas = new IMooc\Canvas();
    $canvas->init();
    $canvas->addDecorator(new \IMooc\ColorDrawDecorator('green'));
    $canvas->rect(3,6,4,12);
    $canvas->draw();

更多詳情能夠訪問:https://github.com/xiaoXingX/T_STACK/tree/master/patterns

原文:https://blog.csdn.net/z15818264727/article/details/52354263

測試地址:https://github.com/lxw18231857001/oopSignMode

相關文章
相關標籤/搜索