1,選擇一個最適合的設計模式
沒有任何事物是完美的,也沒有人說過設計模式一個嚴格的放之四海而皆準的解決方法。因此你可以改變這些模式,使它們更適合手邊的工作。對某些設計模式而言,他們就是所屬程式固有的天性;而對於其他的一些設計模式,你可以改變自己的模式。模式之間互相配合、協同工作已經很常見。它們構成了整個應用(至少一部分)的基礎。
2.單例模式
-
-
// The Database class represents our global DB connection
- class Database{
- // A holdic v. our single instance
- private static $_instance = null;
-
- // Make the constructor private to ensure singleton
- private function __construct()
- {
- private function __construct()
- { }
// A method to get our singleton instance
- public static function getInstance()
- {
- if (!(self::$_instance instanceof Database)) {
- self::$_instance = new Database();
- }
-
- return self::$_instance;
- }
- }
$database = Database::getInstance();
- var_dump($database);
-
複製程式碼
問題:使用單單>複製程式碼
問題:使用單單>複製程式碼
問題:使用單單>複製程式碼-
-
- 問題:使用單單>複製程式碼
-
-
- 問題:使用單單>複製程式碼
-
-
- 問題:使用單單>複製程式碼
-
-
- 問題:使用單單>複製程式碼
-
-
- 問題:使用單單>複製碼範例模式不能建立兩個實例,可用Traits解決建立兩個不同類型的實例的問題,但仍無法解決建立兩個相同實例的問題(可用登錄模式解決)。
-
- 建立兩個不同類別的實例 程式碼:
-
-
-
-
-
- trait Singleton {
- private static $_instance = null;
-
- public static ftion get getption $ __CLASS__;
-
- if(!(self::$_instance instanceof $class)) {
- self::$_instance = new $class;
- }
-
- return self:: $_instance;
- }
-
- }
- 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類別:
-
-
class Registry {
- /**
- * @var array 所有物件的儲存
- */
- static private $_store = array();
-
- /**
- * 將物件新增至登錄機碼
- *
- * 如果不指定名稱,則使用類別名稱
- *
- * @param mix $object 要儲存的物件
- * @param string $name 用於檢索物件的名稱
- * @return void
- * @throws Exception
- */
- static public function add($object, $name = null)
- {
- // Use the classname if no name given, simulates singleton
- $name = (!is_null($name)) ?$name:get_class($object);
- if (isset(self::$_store[$name])) {
- throw new Exception(" Object already exists in registry");
- }
-
- self::$_store[$name]= $object;
- }
-
- /**
- * 從登錄機碼取得一個物件
- *
- * @param string $name 物件名稱,{@see self::set()}
- * @return mix
- * @throws Exception
- */
- static public function get($name)
- {
- if (!self::contains($name)) {
- throw new Exception("Object does not exist in registry");
- }
return self::$_store[$name];
- }
-
- /**
- * 檢查物件是否在登錄中
- *
- * @param string $name 物件名稱,{@see self::set()}
- * @return bool
- */
- static public function contains($name )
- {
- if (!isset(self::$_store[$name])) {
- return false;
- }
-
- return true;
- }
-
- /**
- * 從註冊表中刪除一個物件
- *
- * @param string $name 物件名稱,{@see self::set()}
- * @returns void
- */
- static public function remove($name)
- {
- if (self::contains($name)) {
- unset(self:: $_store[$name]);
- }
- }
- }
-
-
複製代碼
在類別外部,使用Registry類別:
-
-
require 'Registry.php';
class DBReadConnection {}
- class DBWrite {}
$read = new DBReadConnection;
- Registry::add($read);
$write = new DBWriteConnection;
- Registry ::add($write);
// To get the instances, anywhere in our code:
- $read = Registry::get('DBReadConnection');
- $ write = Registry::get('DBWriteConnection');
var_dump($read);
- var_dump($write);
-
-
複製程式碼
在類別內部使用Registry表類,使用者不與Registry互動。
範例程式碼:
-
-
require 'Registry.php';
abstract class DBConnection {
- static public function getInstance($name = null)
- {
- // Get the late-static-binding version of __CLASS__
- $class = get_called_class();
- // Allow passing in a name to get multiple instances
- // If you do not pass a name, it functions as a singleton
- $name = (!is_null($name)) ? $name:$class;
- if (!Registry::contains ($name)) {
- $instance = new $class();
- Registry::add($instance, $name);
- }
- return Registry::get($name);
- }
- }
class DBWriteConnection extends DBConnection {
- public function __construct()
- {
- echo 'DBWConnectiona
';
- {
- echo 'DBWConnectiona
';
- ';
- }
- }
class DBReadConnection extends DBConnection {
- public function __construct()
- {
- echo 'DBRead
';
- Connection
- echo 'DBRead
';
- Connection
- Connection
}
$dbWriteConnection = DBWriteConnection::getInstance('abc');var_dump($dbWriteConnection);$dbReadConnection = DBRead::getInstance(); var_dump($dbReadConnection);
複製程式碼4.工廠模式
工廠(factory)模式製造對象,就像工業界與它同名的鋼筋混泥土產業一樣。通常,我們將工廠模式用於初始化相同抽象類別或介面的具體實作。
在通常方式下,雖然人們極少採用工廠模式,但是它仍是最適合初始化基於驅動安裝的許多變種的一種。例如不同的配置、會話或快取儲存引擎。工廠模式的最大價值在於它可以將多個物件設定封裝成單一、簡單的方法呼叫。
-
- /**
- * 日誌工廠
- *
- * 設定並傳回檔案、mysql 或 sqlite 記錄器
- */
- class Log_Factory {
- /**
- * 取得日誌物件
- *
- * @param string $type 日誌記錄後端的類型,檔案、mysql 或 sqlite
- * @param array $options 日誌類別選項
- */
- public function Log( $type = 'file', array $options)
- {
- // Normalize the type to lowercase
- $type = strtolower($type);
-
- // Figure out the class name and include it
- $class = "Log_" .ucfirst($type);
- require_once str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
-
- // Instantiate the class and set the appropriate options
- $log = new $class($options);
- switch ($type) {
- case 'file':
- $log->setPath($options[' location']);
- break;
- case 'mysql':
- $log->setUser($options['username']);
- $log->setPassword($options['password ']);
- $log->setDBName($options['location']);
- break;
- case 'sqlite':
- $log->setDBPath($otions['location' ]);
- break;
- }
-
- return $log;
- }
- }
複製代碼
5.迭代模式
迭代模式允許我們將foreach的性能添加到任何物件的內部儲存數據,而不僅僅添加到公共屬性。它覆蓋了預設的foreach行為,並允許我們為循環注入業務邏輯。
(1)使用Iterator迭代器接口
-
-
class BasicIterator implements Iterator {
- private $key = 0;
- private $data = array( "world",
- );
public function __construct() {
- $this->key = 0;
- }
public function rewind() {
- $this->key = 0;
- }
public function current() {
- return $this ->data[$this->key];
- }
public function key() {
- return $this->key;
- }
public function next() {
- $this->key++;
- return true;
- }
public function valid() {
- return isset($this->data[$this->key]);
- }
- }
$iterator = new BasicIterator();
- $iterator->rewind ();
do {
- $key = $iterator->key();
- $value = $iterator->current();
- echo $key . ': ' .$value . PHP_EOL;
- } while ($iterator->next() && $iterator->valid());
- $iterator = new BasicIterator ();
- foreach ($iterator as $key => $value) {
- echo $key .': ' .$value . PHP_EOL;
- }
-
-
複製程式碼
(2)使用RecursiveIteratorIterator迭代器遍歷數組
-
$array = array(
- "Hello", // Level 1
- array(
- "World " // Level 2
- ),
- array(
- "How", // Level 2
- array(
- "are", // Level 3
- "you" // Level 3
- )
- ),
- "doing?" // Level 1
- );
$recursiveIterator = new RecursiveArrayIterator($array);
$recursiveIteratorIterator = new RecursiveIteratorIterator($recursiveIterator);
foreach ($recursiveIteratorIterator as $key => $value) {
- echo "Depth: " value. recursiveIteratorIterator->getDepth() . PHP_EOL;
- echo "Key: " . $key . PHP_EOL;
- echo "Value: " .$value . PHP_EOL;
- }
-
-
複製程式碼 (3)用FilterIterator迭代器實現過濾
-
-
class EvenFilterIterator extends FilterIterator {
- /**
- * 僅接受偶數鍵值
- *
- * @return bool
- > / {
- // 取得實際的迭代器
- $iterator = $this->getInnerIterator();
-
- // 取得目前的key
- $ key = $iterator->key();
-
- // 檢查偶數鍵
- if ($key % 2 == 0) {
- return true;
- }
-
- return false;
- }
- }
$array = array(
- 0 => "你好",
- 1 => "每個人都是”,
- 2 => 「我」,
- 3 => 「太棒了」,
- 4 => 「那個」,
- 5 => 「誰」,
- 6 => "Doctor" ,
- 7 => "Lives"
- );
// 從我們的陣列建立一個迭代器
- $ iterator = new ArrayIterator($array); p>
// 建立FilterIterator
- $filterIterator = new EvenFilterIterator($iterator);
foreach ($filterIterator as $key => $value) {
- echo $key .': '. $價值。 PHP_EOL;
- }
- ?>
-
-
複製程式碼
(4)RegexIterator迭代器
-
// 建立一個RecursiveDirectoryIterator
- $directoryIterator = 建立一個RecursiveDirectoryIterator
- $directoryIterator = 建立一個RecursiveDirectoryIterator
- $directoryIterator = 建立一個RecursiveDirectoryIterator
// 建立一個RecursiveIteratorIterator 進行遞歸迭代
- $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);
//ator 建立一個過濾器*. php 檔案
- $regexFilter = new RegexIterator($recursiveIterator, '/(.*?)Iterator(.*?).php$/');
- // 迭代
- foreach ($regexFilter as $key => $file) {
- /* @var SplFileInfo $file */
- echo $file->getFilename() . PHP_EOL;
- }
-
複製程式碼
功能:找到所有的php檔案
(4)LimitItertor迭代器,像SQL中的LIMIT
-
-
-
//定義數組
- $array = array(
- 'Hello',
- '$array = array(
- 'Hello',
- ' ',,,
- '怎麼樣',
- '是',
- '你',
- '做什麼? 🎜>$iterator = new ArrayIterator($array);
// 建立限制迭代器,取得前2 個元素
- $limitIterator = new LimitIterator($ iterator, 0, 2) ;
//迭代
- foreach ($limitIterator as $key => $value) {
- echo $key .': '. $值。 PHP_EOL;
- }
-
複製程式碼
6.觀察者模式(observer)
觀察者模式的核心在於雲霄你的應用程式註冊一個回調,當某個特定的事件發生時便會促發它
-
-
/**
- * 事件類
- *
- * 使用這個類,您可以註冊將
- * 為給定事件調用(先進先出)的回調。
- */
- class Event {
- /**
- * @var array 事件的多維數組 =>回呼
- */
- class Event {
- /**
- * 註冊回呼
- *
- * @param string $eventName 觸發事件的名稱
- * @param mix $callback Event_Callback 或 Closure 的實例
- */
- class Event {
- /**
- * 觸發事件
- *
- * @param string $eventName 要觸發的事件名稱
- * @param mix $data 要傳送到回呼的資料
- */
- class Event {
- /**
- * 執行回呼
- *
- * @param mix $callback Event_Callback 或閉包的實例
- * @param mix $data 傳送到回調的資料
- */
- class Event {
- /**
- * 事件回呼介面
- *
- * 如果你不想使用閉包
- * 你可以定義一個擴充
- * this 的類別。 run 方法將
- * 當事件觸發時被呼叫。
- */
- static protected $callbacks = array();
-
- /**
- * 記錄器回呼
- */
- static public function registerCallback($eventName, $call>back)
- back {
- if (!($callback instanceof Event_Callback) && !($callback instanceof Closure)) {
- throw new Exception("Invalid callback!");
- }
-
- self::$callbacks[$eventName][] = $callback;
- }
-
- /***/
- static public function trigger ($eventName, $data)
- {
- $eventName = strtolower($eventName);
-
- if (isset(self::$callbacks[$eventName])) {
- foreach ( self::$callbacks[$eventName] as $callback) {
- self::callback($callback, $data);
- }
- }
- }
-
- /** */
- static protected function callback($callback, $data)
- {
- if ($callback instanceof Closure) {
- $callback($data);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- } else
- $callback->run($data);
- }
- }
- }
/***/
- interface Event_Callback { public function run($data);
- }
/***/
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.依賴注入模式
依賴注入模式允許類別的使用這為這個類別注入依賴的行為。
-
-
/**
- * 日誌類別
- */
- class Log {
- /**
- * @var Log_Engine_Interface
- */
- protected $engine = false;
-
- /**
- * 將事件新增至日誌
- *
- * @param string $message
- */
- public function add($message)
- {
- if (!$this->engine) {
- throw new Exception('Unable to write log. No Engine set.');
- }
-
- $data['datetime'] = time();
- $data['message' ] = $message;
-
- $session = Registry::get('session');
- $data['user'] = $session->getUserId();
-
- $ this->engine->add($data);
- }
-
- /**
- * 設定日誌資料儲存引擎
- *
- * @param Log_Engine_Interface $Engine
- */
- public function setEngine(Log_Engine_Interface $engine)
- {
- $this ->engine = $engine;
- }
-
- /**
- * 擷取資料儲存引擎
- *
- * @return Log_Engine_Interface
- */
- public function getEngine()
- {
- return $this->engine>;
- ; }
- }
interface Log_Engine_Interface {
- /**
- * 將事件新增至日誌
- *
- * @param string $message
- */
- public function add(array $data);
- }
class Log_Engine_File implements Log_Engine_Interface {
- /**
- * 將事件新增至日誌
- *
- * @param string $message
- */
- public function add(array $data)
- {
- $line = '[' .data('r ', $data['datetime']). '] ' .$data['message']. ' User: ' .$data['user'] . PHP_EOL;
-
- $config = Registry:: get('site-config');
-
- if (!file_put_contents($config['location'], $line, FILE_APPEND)) {
- throw new Exception("An error occurred writing to file. ");
- }
- }
- }
$engine = new Log_Engine_File();
$log = new Log() ;
- $log->setEngine($engine);
// Add it to the registry
- Registry::add($log);
-
複製程式碼
依賴注入不想工廠模式,日之類無需了解每一個不同的儲存引擎的相關知識。這意味著任何使用日誌類別的開發者可以添加他們自己的儲存引擎,主要他們複合介面就行。
8.模型-視圖-控制器
模型-視圖-控制器又稱為MVC模式,是描述應用程式3個不同層次之間關係的一種方式。
模型-資料層 所有的輸出資料都來自模型。它可能是一個資料庫、web服務或文件。
視圖-表現層 負責將資料從模型中取出並輸出給使用者。
控制器-應用程式流程層 根據使用者的請求呼叫對應的模型檢索出請求的數據,然後呼叫視圖將操作的結果顯示給使用者。
一個典型的MVC架構圖:
9.對模式的理解 模式是許多常見問題的最佳解決方法。
您可能感興趣的文章:
- php設計模式單例模式、工廠模式與觀察者模式
- 深入php設計模式實例詳解
- php設計模式實例之指令模式
- php設計模式實例之觀察者模式(2)
- PHP設計模式實例之觀察者模式
- php設計模式實例之工廠模式
- php設計模式實例之單例模式
- PHP設計模式之觀察者模式的例子
- php設計模式之工廠模式的實例代碼
- php設計模式之單例模式的實例程式碼
- php常用設計模式之工廠模式與單例模式介紹
- 學習php設計模式之單例模式
- php常用的三種設計模式的學習筆記
- php設計模式之單例模式學習
|