php essence php design pattern

WBOY
Release: 2016-07-25 09:13:12
Original
925 people have browsed it

1. Choose the most appropriate design pattern

Nothing is perfect, and no one ever said design patterns were a strict one-size-fits-all solution. So you can change these modes to make them more suitable for the job at hand. For some design patterns, they are inherent in the program they belong to; while for other design patterns, you can change the pattern itself. It is common for modes to cooperate and work together. They form the basis of (at least part of) the entire application.

2. Singleton mode

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

  2. class Database{
  3. // A static variable to hold our single instance
  4. private static $_instance = null;
  5. // Make the constructor private to ensure singleton
  6. private function __construct()
  7. {
  8. echo 'constructor';
  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. var_dump($database);

Copy code

Problem: Two instances cannot be created using singleton mode. Traits can be used to solve the problem of creating two The problem of different types of instances, but still does not solve the problem of creating two identical instances (which can be solved by registry mode).

Create two instances of different classes Code:

  1. trait Singleton {
  2. private static $_instance = null;
  3. public static function getInstance() {
  4. $class = __CLASS__;
  5. if(!(self::$_instance instanceof $class)) {
  6. self::$_instance = new $class;
  7. }
  8. return self::$_instance;
  9. }
  10. }
  11. class DB {
  12. }
  13. class DBWriteConnection extends DB {
  14. use Singleton;
  15. private function __construct() {
  16. echo 'DBWriteConnection
    ';
  17. }
  18. }
  19. class DBReadConnection extends DB {
  20. use Singleton;
  21. private function __construct() {
  22. echo 'DBReadConnection
    ';
  23. }
  24. }
  25. $dbWriteConnection = DBWriteConnection::getInstance();
  26. var_dump($dbWriteConnection);
Copy code

3. Registry mode The registry pattern is simply a single global class that allows code to retrieve the same instance of an object when you need it, and to create another instance when you need it (those global instances will be accessed again on request).

Registry class:

  1. class Registry {

  2. /**
  3. * @var array The store for all of our objects
  4. */
  5. static private $_store = array();
  6. /**
  7. * Add an object to the registry
  8. *
  9. * If you do not specify a name the classname is used
  10. *
  11. * @param mixed $object The object to store
  12. * @param string $name Name used to retrieve the object
  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. * Get an object from the registry
  27. *
  28. * @param string $name Object name, {@see self::set()}
  29. * @return mixed
  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. * Check if an object is in the registry
  41. *
  42. * @param string $name Object 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. * Remove an object from the registry
  54. *
  55. * @param string $name Object 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. }
Copy code

Outside the class, use the Registry class:

  1. require 'Registry.php';

  2. class DBReadConnection {}

  3. class DBWriteConnection {}

  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);
Copy code

Use the Registry table class inside the class, and the user does not interact with the Registry.

Sample code:

  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 'DBWriteConnection
    ' ;
  21. }
  22. }

  23. class DBReadConnection extends DBConnection {

  24. public function __construct()
  25. {
  26. echo 'DBReadConnection
    ';
  27. }
  28. }

  29. < ;p>$dbWriteConnection = DBWriteConnection::getInstance('abc');
  30. var_dump($dbWriteConnection);
  31. $dbReadConnection = DBReadConnection::getInstance();
  32. var_dump($dbReadConnection);

Copy code

4.Factory mode The factory pattern manufactures objects, just like its namesake steel and concrete industry. Usually, we use the factory pattern to initialize concrete implementations of the same abstract class or interface.

In general, although factory mode is rarely used, it is still the most suitable for initializing many variants of driver-based installation. For example different configurations, sessions or caching storage engines. The greatest value of the factory pattern is that it can encapsulate multiple object settings into a single, simple method call.

  1. /**
  2. * Log Factory
  3. *
  4. * Setup and return a file, mysql, or sqlite logger
  5. */
  6. class Log_Factory {
  7. /**
  8. * Get a log object
  9. *
  10. * @param string $type The type of logging backend, file, mysql or sqlite
  11. * @param array $options Log class options
  12. */
  13. public function getLog($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. }
Copy code

5. Iteration mode The iteration pattern allows us to add the performance of foreach to the internally stored data of any object, not just to public properties. It overrides the default foreach behavior and allows us to inject business logic into the loop.

(1) Use Iterator interface

  1. class BasicIterator implements Iterator {

  2. private $key = 0;
  3. private $data = array(
  4. "hello",
  5. "world",
  6. );

  7. < ;p> public function __construct() {
  8. $this->key = 0;
  9. }

  10. public function rewind() {

  11. $this->key = 0;
  12. }< ;/p>
  13. public function current() {

  14. return $this->data[$this->key];
  15. }

  16. public function key() {

  17. return $this->key;
  18. }

  19. public function next() {

  20. $this->key++;
  21. return true;
  22. }

  23. return isset($this->data[$this->key]);
  24. }
  25. }

  26. $iterator = new BasicIterator();

  27. $iterator->rewind();

  28. do {

  29. $key = $iterator->key();
  30. $value = $iterator->current();
  31. echo $ key .': ' .$value . PHP_EOL;
  32. } while ($iterator->next() && $iterator->valid());

  33. $iterator = new BasicIterator ();
  34. foreach ($iterator as $key => $value) {
  35. echo $key .': ' .$value . PHP_EOL;
  36. }

Copy code

(2 ) Traverse the array using the RecursiveIteratorIterator iterator

  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: " . $recursiveIteratorIterator->getDepth() . PHP_EOL;
  19. echo "Key: " . $key . PHP_EOL;
  20. echo "Value: " .$value . PHP_EOL;
  21. }
Copy code

(3)用FilterIterator迭代器实现过滤

  1. class EvenFilterIterator extends FilterIterator {

  2. /**
  3. * Accept only even-keyed values
  4. *
  5. * @return bool
  6. */
  7. public function accept()
  8. {
  9. // Get the actual iterator
  10. $iterator = $this->getInnerIterator();
  11. // Get the current key
  12. $key = $iterator->key();
  13. // Check for even keys
  14. if ($key % 2 == 0) {
  15. return true;
  16. }
  17. return false;
  18. }
  19. }

  20. $array = array(

  21. 0 => "Hello",
  22. 1 => "Everybody Is",
  23. 2 => "I'm",
  24. 3 => "Amazing",
  25. 4 => "The",
  26. 5 => "Who",
  27. 6 => "Doctor",
  28. 7 => "Lives"
  29. );

  30. // Create an iterator from our array

  31. $iterator = new ArrayIterator($array);

  32. // Create our FilterIterator

  33. $filterIterator = new EvenFilterIterator($iterator);

  34. // Iterate

  35. foreach ($filterIterator as $key => $value) {
  36. echo $key .': '. $value . PHP_EOL;
  37. }
  38. ?>

复制代码

(4)RegexIterator迭代器

  1. // Create a RecursiveDirectoryIterator
  2. $directoryIterator = new RecursiveDirectoryIterator("./");

  3. // Create a RecursiveIteratorIterator to recursively iterate

  4. $recursiveIterator = new RecursiveIteratorIterator($directoryIterator);

  5. // Createa filter for *Iterator*.php files

  6. $regexFilter = new RegexIterator($recursiveIterator, '/(.*?)Iterator(.*?).php$/');

  7. // Iterate

  8. foreach ($regexFilter as $key => $file) {
  9. /* @var SplFileInfo $file */
  10. echo $file->getFilename() . PHP_EOL;
  11. }
复制代码

功能:找到所有的php文件

(4)LimitItertor迭代器,像SQL中的LIMIT

  1. // Define the array

  2. $array = array(
  3. 'Hello',
  4. 'World',
  5. 'How',
  6. 'are',
  7. 'you',
  8. 'doing?'
  9. );

  10. // Create the iterator

  11. $iterator = new ArrayIterator($array);

  12. // Create the limiting iterator, to get the first 2 elements

  13. $limitIterator = new LimitIterator($iterator, 0, 2);

  14. // Iterate

  15. foreach ($limitIterator as $key => $value) {
  16. echo $key .': '. $value . PHP_EOL;
  17. }

复制代码

6. Observer mode (observer)

The core of the observer pattern is that your application registers a callback, which will trigger it when a specific event occurs.

  1. /**

  2. * The Event Class
  3. *
  4. * With this class you can register callbacks that will
  5. * be called (FIFO) for a given event.
  6. */
  7. class Event {
  8. /**
  9. * @var array A multi-dimentional array of events => callbacks
  10. */
  11. static protected $callbacks = array();
  12. / **
  13. * Register a callback
  14. *
  15. * @param string $eventName Name of the triggering event
  16. * @param mixed $callback An instance of Event_Callback or a Closure
  17. */
  18. static public function registerCallback($eventName, $callback)
  19. {
  20. if (!($callback instanceof Event_Callback) && !($callback instanceof Closure)) {
  21. throw new Exception("Invalid callback! ");
  22. }
  23. $eventName = strtolower($eventName);
  24. self::$callbacks[$eventName][] = $callback;
  25. }
  26. /**
  27. * Trigger an event
  28. *
  29. * @param string $eventName Name of the event to be triggered
  30. * @param mixed $data The data to be sent to the callback
  31. */
  32. static public function trigger ($eventName, $data)
  33. {
  34. $eventName = strtolower($eventName);
  35. if (isset(self::$callbacks[$eventName])) {
  36. foreach (self::$callbacks[$eventName] as $callback) {
  37. self::callback($callback, $data);
  38. }
  39. }
  40. }
  41. /**
  42. * Perform the callback
  43. *
  44. * @param mixed $callback An instance of Event_Callback or a Closure
  45. * @param mixed $data The data sent to the callback
  46. */
  47. static protected function callback($callback, $data)
  48. {
  49. if ( $callback instanceof Closure) {
  50. $callback($data);
  51. } else {
  52. $callback->run($data);
  53. }
  54. }
  55. }

  56. /**

  57. * The Event Callback interface
  58. *
  59. * If you do not wish to use a closure
  60. * you can define a class that extends
  61. * this instead. The run method will be
  62. * called when the event is triggered.
  63. */
  64. interface Event_Callback {
  65. public function run($data);
  66. }

  67. /**

  68. * Logger callback
  69. */
  70. class LogCallback implements Event_Callback {
  71. public function run($data )
  72. {
  73. echo "Log Data" . PHP_EOL;
  74. var_dump($data);
  75. }
  76. }

  77. // Register the log callback

  78. Event::registerCallback('save', new LogCallback());

  79. // Register the clear cache callback as a closure

  80. Event::registerCallback('save', function ($data) {
  81. echo "Clear Cache" . PHP_EOL;
  82. var_dump($data);
  83. });

  84. class MyDataRecord {

  85. public function save()
  86. {
  87. // Save data
  88. // Trigger the save event
  89. Event::trigger ('save', array("Hello", "World"));
  90. }
  91. }

  92. // Instantiate a new data record

  93. $data = new MyDataRecord();
  94. $data ->save(); // 'save' Event is triggered here

Copy code

7. Dependency injection mode Dependency injection pattern allows classes to use this behavior to inject dependencies into this class.

  1. /**

  2. * Log Class
  3. */
  4. class Log {
  5. /**
  6. * @var Log_Engine_Interface
  7. */
  8. protected $engine = false;
  9. /**
  10. * Add an event to the log
  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. * Set the log data storage engine
  27. *
  28. * @param Log_Engine_Interface $Engine
  29. */
  30. public function setEngine(Log_Engine_Interface $engine)
  31. {
  32. $this->engine = $engine ;
  33. }
  34. /**
  35. * Retrieve the data storage engine
  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. * Add an event to the log
  47. *
  48. * @param string $message
  49. */
  50. public function add(array $data);
  51. }

  52. class Log_Engine_File implements Log_Engine_Interface {

  53. /**
  54. * Add an event to the log
  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);

Copy code

Dependency injection does not require factory mode, and there is no need to understand the relevant knowledge of each different storage engine. This means that any developer using the logging class can add their own storage engine and simply compose the interface.

8. Model-View-Controller Model-View-Controller, also known as the MVC pattern, is a way of describing the relationship between three different levels of an application. Model-Data Layer All output data comes from the model. It may be a database, web service or file. View-presentation layer is responsible for taking data out of the model and outputting it to the user. The controller-application flow layer calls the corresponding model according to the user's request to retrieve the requested data, and then calls the view to display the results of the operation to the user.

A typical MVC architecture diagram: php mvc架构图

9. Understanding of patterns
Patterns are the best solutions to many common problems.

Articles you may be interested in:

  • php design patterns: singleton mode, factory mode and observer mode
  • In-depth explanation of PHP design pattern examples
  • php design pattern example command pattern
  • php design pattern example observer pattern (2)
  • PHP Design Pattern Example Observer Pattern
  • php design pattern example factory pattern
  • php design pattern example singleton pattern
  • Example of Observer pattern in PHP design pattern
  • PHP design pattern factory pattern example code
  • PHP design pattern singleton pattern example code
  • Introduction to common PHP design patterns: factory pattern and singleton pattern
  • Learn PHP design pattern singleton pattern
  • Study notes on three commonly used design patterns in PHP
  • Learning the Singleton Pattern of PHP Design Pattern


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!