首頁  >  文章  >  後端開發  >  php精粹 php設計模式

php精粹 php設計模式

WBOY
WBOY原創
2016-07-25 09:13:12932瀏覽

1,選擇一個最適合的設計模式

沒有任何事物是完美的,也沒有人說過設計模式一個嚴格的放之四海而皆準的解決方法。因此你可以改變這些模式,使它們更適合手邊的工作。對某些設計模式而言,他們就是所屬程式固有的天性;而對於其他的一些設計模式,你可以改變自己的模式。模式之間互相配合、協同工作已經很常見。它們構成了整個應用(至少一部分)的基礎。

2.單例模式

  1. // The Database class represents our global DB connection

  2. class Database{
  3. // A holdic v. our single instance
  4. private static $_instance = null;
  5. // Make the constructor private to ensure singleton
  6. private function __construct()
  7. {
  8. private function __construct()
  9. { }
  10. // A method to get our singleton instance

  11. public static function getInstance()
  12. {
  13. if (!(self::$_instance instanceof Database)) {
  14. self::$_instance = new Database();
  15. }
  16. return self::$_instance;
  17. }
  18. }
  19. $database = Database::getInstance();

  20. var_dump($database);
複製程式碼

問題:使用單單>複製程式碼

問題:使用單單>複製程式碼
    問題:使用單單>複製程式碼
  1. 問題:使用單單>複製程式碼
  2. 問題:使用單單>複製程式碼
  3. 問題:使用單單>複製程式碼
  4. 問題:使用單單>複製程式碼
  5. 問題:使用單單>複製碼範例模式不能建立兩個實例,可用Traits解決建立兩個不同類型的實例的問題,但仍無法解決建立兩個相同實例的問題(可用登錄模式解決)。
  6. 建立兩個不同類別的實例 程式碼:
  7. trait Singleton {
  8. private static $_instance = null;
  9. public static ftion get getption $ __CLASS__;
  10. if(!(self::$_instance instanceof $class)) {
  11. self::$_instance = new $class;
  12. }
  13. return self:: $_instance;
  14. }
  15. }
  16. class DB {
}
class DBWriteConnection extends DB { s__Svate f🎜>;
echo 'DBWriteConnection
'; } } class DBReadConnection extends DB { use Singleton; private function ) { echo 'DBReadConnection
'; } } $dbWriteConnection = DBWriteConnection::getInstance(); var_dump($dbWriteConnection); 複製程式碼

3.登錄模式 註冊表模式只是一個單獨的全域類,在你需要的時候允許程式碼檢索一個物件的相同實例,也可以在你需要的時創建另一個實例(一經要求將再次存取那些全域實例)。

Registry類別:

  1. class Registry {

  2. /**
  3. * @var array 所有物件的儲存
  4. */
  5. static private $_store = array();
  6. /**
  7. * 將物件新增至登錄機碼
  8. *
  9. * 如果不指定名稱,則使用類別名稱
  10. *
  11. * @param mix $object 要儲存的物件
  12. * @param string $name 用於檢索物件的名稱
  13. * @return void
  14. * @throws Exception
  15. */
  16. static public function add($object, $name = null)
  17. {
  18. // Use the classname if no name given, simulates singleton
  19. $name = (!is_null($name)) ?$name:get_class($object);
  20. if (isset(self::$_store[$name])) {
  21. throw new Exception(" Object already exists in registry");
  22. }
  23. self::$_store[$name]= $object;
  24. }
  25. /**
  26. * 從登錄機碼取得一個物件
  27. *
  28. * @param string $name 物件名稱,{@see self::set()}
  29. * @return mix
  30. * @throws Exception
  31. */
  32. static public function get($name)
  33. {
  34. if (!self::contains($name)) {
  35. throw new Exception("Object does not exist in registry");
  36. }
  37. return self::$_store[$name];

  38. }
  39. /**
  40. * 檢查物件是否在登錄中
  41. *
  42. * @param string $name 物件名稱,{@see self::set()}
  43. * @return bool
  44. */
  45. static public function contains($name )
  46. {
  47. if (!isset(self::$_store[$name])) {
  48. return false;
  49. }
  50. return true;
  51. }
  52. /**
  53. * 從註冊表中刪除一個物件
  54. *
  55. * @param string $name 物件名稱,{@see self::set()}
  56. * @returns void
  57. */
  58. static public function remove($name)
  59. {
  60. if (self::contains($name)) {
  61. unset(self:: $_store[$name]);
  62. }
  63. }
  64. }
複製代碼

在類別外部,使用Registry類別:

  1. require 'Registry.php';

  2. class DBReadConnection {}

  3. class DBWrite {}
  4. $read = new DBReadConnection;

  5. Registry::add($read);
  6. $write = new DBWriteConnection;

  7. Registry ::add($write);
  8. // To get the instances, anywhere in our code:

  9. $read = Registry::get('DBReadConnection');
  10. $ write = Registry::get('DBWriteConnection');
  11. var_dump($read);

  12. var_dump($write);
複製程式碼

在類別內部使用Registry表類,使用者不與Registry互動。

範例程式碼:

  1. require 'Registry.php';

  2. abstract class DBConnection {

  3. static public function getInstance($name = null)
  4. {
  5. // Get the late-static-binding version of __CLASS__
  6. $class = get_called_class();
  7. // Allow passing in a name to get multiple instances
  8. // If you do not pass a name, it functions as a singleton
  9. $name = (!is_null($name)) ? $name:$class;
  10. if (!Registry::contains ($name)) {
  11. $instance = new $class();
  12. Registry::add($instance, $name);
  13. }
  14. return Registry::get($name);
  15. }
  16. }
  17. class DBWriteConnection extends DBConnection {

  18. public function __construct()
  19. {
  20. echo 'DBWConnectiona
    ';
  21. {
  22. echo 'DBWConnectiona
    ';
  23. ';
  24. }
  25. }
  26. class DBReadConnection extends DBConnection {

  27. public function __construct()
  28. {
  29. echo 'DBRead
    ';
  30. Connection
  31. echo 'DBRead
    ';
  32. Connection
  33. Connection
}

$dbWriteConnection = DBWriteConnection::getInstance('abc');var_dump($dbWriteConnection);$dbReadConnection = DBRead::getInstance(); var_dump($dbReadConnection);

複製程式碼

4.工廠模式 工廠(factory)模式製造對象,就像工業界與它同名的鋼筋混泥土產業一樣。通常,我們將工廠模式用於初始化相同抽象類別或介面的具體實作。

在通常方式下,雖然人們極少採用工廠模式,但是它仍是最適合初始化基於驅動安裝的許多變種的一種。例如不同的配置、會話或快取儲存引擎。工廠模式的最大價值在於它可以將多個物件設定封裝成單一、簡單的方法呼叫。

  1. /**
  2. * 日誌工廠
  3. *
  4. * 設定並傳回檔案、mysql 或 sqlite 記錄器
  5. */
  6. class Log_Factory {
  7. /**
  8. * 取得日誌物件
  9. *
  10. * @param string $type 日誌記錄後端的類型,檔案、mysql 或 sqlite
  11. * @param array $options 日誌類別選項
  12. */
  13. public function Log( $type = 'file', array $options)
  14. {
  15. // Normalize the type to lowercase
  16. $type = strtolower($type);
  17. // Figure out the class name and include it
  18. $class = "Log_" .ucfirst($type);
  19. require_once str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
  20. // Instantiate the class and set the appropriate options
  21. $log = new $class($options);
  22. switch ($type) {
  23. case 'file':
  24. $log->setPath($options[' location']);
  25. break;
  26. case 'mysql':
  27. $log->setUser($options['username']);
  28. $log->setPassword($options['password ']);
  29. $log->setDBName($options['location']);
  30. break;
  31. case 'sqlite':
  32. $log->setDBPath($otions['location' ]);
  33. break;
  34. }
  35. return $log;
  36. }
  37. }
複製代碼

5.迭代模式 迭代模式允許我們將foreach的性能添加到任何物件的內部儲存數據,而不僅僅添加到公共屬性。它覆蓋了預設的foreach行為,並允許我們為循環注入業務邏輯。

(1)使用Iterator迭代器接口

  1. class BasicIterator implements Iterator {

  2. private $key = 0;
  3. private $data = array( "world",
  4. );
  5. public function __construct() {

  6. $this->key = 0;
  7. }
  8. public function rewind() {

  9. $this->key = 0;
  10. }
  11. public function current() {

  12. return $this ->data[$this->key];
  13. }
  14. public function key() {

  15. return $this->key;
  16. }
  17. public function next() {

  18. $this->key++;
  19. return true;
  20. }
  21. public function valid() {

  22. return isset($this->data[$this->key]);
  23. }
  24. }
  25. $iterator = new BasicIterator();

  26. $iterator->rewind ();
  27. do {

  28. $key = $iterator->key();
  29. $value = $iterator->current();
  30. echo $key . ': ' .$value . PHP_EOL;
  31. } while ($iterator->next() && $iterator->valid());
  32. $iterator = new BasicIterator ();
  33. foreach ($iterator as $key => $value) {
  34. echo $key .': ' .$value . PHP_EOL;
  35. }
複製程式碼
(2)使用RecursiveIteratorIterator迭代器遍歷數組

  1. $array = array(

  2. "Hello", // Level 1
  3. array(
  4. "World " // Level 2
  5. ),
  6. array(
  7. "How", // Level 2
  8. array(
  9. "are", // Level 3
  10. "you" // Level 3
  11. )
  12. ),
  13. "doing?" // Level 1
  14. );
  15. $recursiveIterator = new RecursiveArrayIterator($array);

  16. $recursiveIteratorIterator = new RecursiveIteratorIterator($recursiveIterator);

  17. foreach ($recursiveIteratorIterator as $key => $value) {

  18. echo "Depth: " value. recursiveIteratorIterator->getDepth() . PHP_EOL;
  19. echo "Key: " . $key . PHP_EOL;
  20. echo "Value: " .$value . PHP_EOL;
  21. }
複製程式碼

(3)用FilterIterator迭代器實現過濾

  1. class EvenFilterIterator extends FilterIterator {

  2. /**
  3. * 僅接受偶數鍵值
  4. *
  5. * @return bool
  6. > / {
  7. // 取得實際的迭代器
  8. $iterator = $this->getInnerIterator();
  9. // 取得目前的key
  10. $ key = $iterator->key();
  11. // 檢查偶數鍵
  12. if ($key % 2 == 0) {
  13. return true;
  14. }
  15. return false;
  16. }
  17. }
  18. $array = array(

  19. 0 => "你好",
  20. 1 => "每個人都是”,
  21. 2 => 「我」,
  22. 3 => 「太棒了」,
  23. 4 => 「那個」,
  24. 5 => 「誰」,
  25. 6 => "Doctor" ,
  26. 7 => "Lives"
  27. );
  28. // 從我們的陣列建立一個迭代器

  29. $ iterator = new ArrayIterator($array); p>
  30. // 建立FilterIterator

  31. $filterIterator = new EvenFilterIterator($iterator);
  32. foreach ($filterIterator as $key => $value) {

  33. echo $key .': '. $價值。 PHP_EOL;
  34. }
  35. ?>
複製程式碼
(4)RegexIterator迭代器

  1. // 建立一個RecursiveDirectoryIterator

  2. $directoryIterator = 建立一個RecursiveDirectoryIterator
  3. $directoryIterator = 建立一個RecursiveDirectoryIterator
  4. $directoryIterator = 建立一個RecursiveDirectoryIterator
  5. // 建立一個RecursiveIteratorIterator 進行遞歸迭代

  6. $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);
  7. //ator 建立一個過濾器*. php 檔案

  8. $regexFilter = new RegexIterator($recursiveIterator, '/(.*?)Iterator(.*?).php$/');
  9. // 迭代
  10. foreach ($regexFilter as $key => $file) {
  11. /* @var SplFileInfo $file */
  12. echo $file->getFilename() . PHP_EOL;
  13. }
複製程式碼

功能:找到所有的php檔案

(4)LimitItertor迭代器,像SQL中的LIMIT
  1. //定義數組

  2. $array = array(
  3. 'Hello',
  4. '$array = array(
  5. 'Hello',
  6. ' ',,,
  7. '怎麼樣',
  8. '是',
  9. '你',
  10. '做什麼? 🎜>$iterator = new ArrayIterator($array);
  11. // 建立限制迭代器,取得前2 個元素

  12. $limitIterator = new LimitIterator($ iterator, 0, 2) ;
  13. //迭代

  14. foreach ($limitIterator as $key => $value) {
  15. echo $key .': '. $值。 PHP_EOL;
  16. }
複製程式碼

6.觀察者模式(observer)

觀察者模式的核心在於雲霄你的應用程式註冊一個回調,當某個特定的事件發生時便會促發它

  1. /**

  2. * 事件類
  3. *
  4. * 使用這個類,您可以註冊將
  5. * 為給定事件調用(先進先出)的回調。
  6. */
  7. class Event {
  8. /**
  9. * @var array 事件的多維數組 =>回呼
  10. */
  11. class Event {
  12. /**
  13. * 註冊回呼
  14. *
  15. * @param string $eventName 觸發事件的名稱
  16. * @param mix $callback Event_Callback 或 Closure 的實例
  17. */
  18. class Event {
  19. /**
  20. * 觸發事件
  21. *
  22. * @param string $eventName 要觸發的事件名稱
  23. * @param mix $data 要傳送到回呼的資料
  24. */
  25. class Event {
  26. /**
  27. * 執行回呼
  28. *
  29. * @param mix $callback Event_Callback 或閉包的實例
  30. * @param mix $data 傳送到回調的資料
  31. */
  32. class Event {
  33. /**
  34. * 事件回呼介面
  35. *
  36. * 如果你不想使用閉包
  37. * 你可以定義一個擴充
  38. * this 的類別。 run 方法將
  39. * 當事件觸發時被呼叫。
  40. */
  41. static protected $callbacks = array();
  42. /**
  43. * 記錄器回呼
  44. */
  45. static public function registerCallback($eventName, $call>back)
  46. back {
  47. if (!($callback instanceof Event_Callback) && !($callback instanceof Closure)) {
  48. throw new Exception("Invalid callback!");
  49. }
  50. self::$callbacks[$eventName][] = $callback;
  51. }
  52. /***/
  53. static public function trigger ($eventName, $data)
  54. {
  55. $eventName = strtolower($eventName);
  56. if (isset(self::$callbacks[$eventName])) {
  57. foreach ( self::$callbacks[$eventName] as $callback) {
  58. self::callback($callback, $data);
  59. }
  60. }
  61. }
  62. /** */
  63. static protected function callback($callback, $data)
  64. {
  65. if ($callback instanceof Closure) {
  66. $callback($data);
  67. }
  68. }
  69. }
  70. }
  71. }
  72. }
  73. }
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }
  81. }
  82. }
  83. }
  84. }
  85. }
  86. }
  87. } else
  88. $callback->run($data);
  89. }
  90. }
  91. }
  92. /***/

  93. interface Event_Callback { public function run($data);
  94. }
  95. /***/

class LogCallback implements Event_Callback {
public function run($data) { echo "Log Data" . PHP_EOL;
var_dump($data); }}

// Register the log callbackEvent::registerCallback('save', new LogCallback());

// Register the clear cache callback as a closureEvent::registerCallback('save', function ( $data) { echo "Clear Cache" . PHP_EOL; var_dump($data); });

class MyDataRecord { public function save( ) { // Save data // Trigger the save event Event::trigger('save', array("Hello", "World")); }}

// Instantiate a new data record$data = new MyDataRecord();$data->save(); // 'save' Event is triggered here

複製程式碼

7.依賴注入模式 依賴注入模式允許類別的使用這為這個類別注入依賴的行為。

  1. /**

  2. * 日誌類別
  3. */
  4. class Log {
  5. /**
  6. * @var Log_Engine_Interface
  7. */
  8. protected $engine = false;
  9. /**
  10. * 將事件新增至日誌
  11. *
  12. * @param string $message
  13. */
  14. public function add($message)
  15. {
  16. if (!$this->engine) {
  17. throw new Exception('Unable to write log. No Engine set.');
  18. }
  19. $data['datetime'] = time();
  20. $data['message' ] = $message;
  21. $session = Registry::get('session');
  22. $data['user'] = $session->getUserId();
  23. $ this->engine->add($data);
  24. }
  25. /**
  26. * 設定日誌資料儲存引擎
  27. *
  28. * @param Log_Engine_Interface $Engine
  29. */
  30. public function setEngine(Log_Engine_Interface $engine)
  31. {
  32. $this ->engine = $engine;
  33. }
  34. /**
  35. * 擷取資料儲存引擎
  36. *
  37. * @return Log_Engine_Interface
  38. */
  39. public function getEngine()
  40. {
  41. return $this->engine>;
  42. ; }
  43. }
  44. interface Log_Engine_Interface {

  45. /**
  46. * 將事件新增至日誌
  47. *
  48. * @param string $message
  49. */
  50. public function add(array $data);
  51. }
  52. class Log_Engine_File implements Log_Engine_Interface {

  53. /**
  54. * 將事件新增至日誌
  55. *
  56. * @param string $message
  57. */
  58. public function add(array $data)
  59. {
  60. $line = '[' .data('r ', $data['datetime']). '] ' .$data['message']. ' User: ' .$data['user'] . PHP_EOL;
  61. $config = Registry:: get('site-config');
  62. if (!file_put_contents($config['location'], $line, FILE_APPEND)) {
  63. throw new Exception("An error occurred writing to file. ");
  64. }
  65. }
  66. }
  67. $engine = new Log_Engine_File();

  68. $log = new Log() ;

  69. $log->setEngine($engine);
  70. // Add it to the registry

  71. Registry::add($log);
複製程式碼

依賴注入不想工廠模式,日之類無需了解每一個不同的儲存引擎的相關知識。這意味著任何使用日誌類別的開發者可以添加他們自己的儲存引擎,主要他們複合介面就行。

8.模型-視圖-控制器 模型-視圖-控制器又稱為MVC模式,是描述應用程式3個不同層次之間關係的一種方式。 模型-資料層 所有的輸出資料都來自模型。它可能是一個資料庫、web服務或文件。 視圖-表現層 負責將資料從模型中取出並輸出給使用者。 控制器-應用程式流程層 根據使用者的請求呼叫對應的模型檢索出請求的數據,然後呼叫視圖將操作的結果顯示給使用者。

一個典型的MVC架構圖: php mvc架构图

9.對模式的理解
模式是許多常見問題的最佳解決方法。

您可能感興趣的文章:

  • php設計模式單例模式、工廠模式與觀察者模式
  • 深入php設計模式實例詳解
  • php設計模式實例之指令模式
  • php設計模式實例之觀察者模式(2)
  • PHP設計模式實例之觀察者模式
  • php設計模式實例之工廠模式
  • php設計模式實例之單例模式
  • PHP設計模式之觀察者模式的例子
  • php設計模式之工廠模式的實例代碼
  • php設計模式之單例模式的實例程式碼
  • php常用設計模式之工廠模式與單例模式介紹
  • 學習php設計模式之單例模式
  • php常用的三種設計模式的學習筆記
  • php設計模式之單例模式學習


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn