0

0

php精粹 php设计模式

php中文网

php中文网

发布时间:2016-07-25 09:13:12

|

1012人浏览过

|

来源于php中文网

原创

1,选择一个最合适的设计模式

没有任何事物是完美的,也没有人说过设计模式一个严格的放之四海而皆准的解决方法。因此你可以改变这些模式,使它们更适合手头的工作。对于某些设计模式而言,他们就是所属程序固有的天性;而对于其他的一些设计模式,你可以改变其自身的模式。模式之间互相配合、协同工作已经很常见。它们构成了整个应用(至少一部分)的基础。

2.单例模式

  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. $database = Database::getInstance();

  20. var_dump($database);

    立即学习PHP免费学习笔记(深入)”;

复制代码

问题:使用单例模式不能创建两个实例,可用Traits解决创建两个不同类型的实例的问题,但仍然不能解决创建两个相同实例的问题(可用注册表模式解决)。

创建两个不同类的实例 代码:

  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);
复制代码

3.注册表模式 注册表模式仅仅是一个单独的全局类,在你需要的时候允许代码检索一个对象的相同实例,也可以在你需要的时创建另一个实例(一经要求将再次访问那些全局实例)。

Registry类:

  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. }
复制代码

在类外部,使用Registry类:

  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);
复制代码

在类内部使用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 'DBWriteConnection
    ';
  21. }
  22. }
  23. class DBReadConnection extends DBConnection {

  24. public function __construct()
  25. {
  26. echo 'DBReadConnection
    ';
  27. }
  28. }
  29. $dbWriteConnection = DBWriteConnection::getInstance('abc');

  30. var_dump($dbWriteConnection);
  31. $dbReadConnection = DBReadConnection::getInstance();
  32. var_dump($dbReadConnection);
复制代码

4.工厂模式 工厂(factory)模式制造对象,就像工业界与它同名的钢筋混泥土行业一样。通常,我们将工厂模式用于初始化相同抽象类或者接口的具体实现。

在通常方式下,虽然人们极少采用工厂模式,但是它仍是最适合初始化基于驱动安装的许多变种的一种。例如不同的配置、会话或缓存存储引擎。工厂模式的最大价值在于它可以将多个对象设置封装成单一、简单的方法调用。

  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. }
复制代码

5.迭代模式 迭代模式允许我们将foreach的性能添加到任何对象的内部存储数据,而不仅仅添加到公共属性。它覆盖了默认的foreach行为,并允许我们为循环注入业务逻辑。

(1)使用Iterator迭代器接口

  1. class BasicIterator implements Iterator {

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

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

  11. $this->key = 0;
  12. }
  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. public function valid() {

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

  28. $iterator->rewind();
  29. do {

  30. $key = $iterator->key();
  31. $value = $iterator->current();
  32. echo $key .': ' .$value . PHP_EOL;
  33. } while ($iterator->next() && $iterator->valid());
  34. $iterator = new BasicIterator();
  35. foreach ($iterator as $key => $value) {
  36. echo $key .': ' .$value . PHP_EOL;
  37. }
复制代码

(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);

    magento(麦进斗)
    magento(麦进斗)

    Magento是一套专业开源的PHP电子商务系统。Magento设计得非常灵活,具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。Magento开源网店系统的特点主要分以下几大类,网站管理促销和工具国际化支持SEO搜索引擎优化结账方式运输快递支付方式客户服务用户帐户目录管理目录浏览产品展示分析和报表Magento 1.6 主要包含以下新特性:•持久性购物 - 为不同的

    下载
  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. }
复制代码

(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)

观察者模式的核心在于云霄你的应用程序注册一个回调,当某个特定的事件发生时便会促发它

  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
复制代码

7.依赖注入模式 依赖注入模式允许类的使用这为这个类注入依赖的行为。

  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);
复制代码

依赖注入不想工厂模式,日之类无需了解每一个不同的存储引擎的相关知识。这就意味着任何使用日志类的开发者可以添加他们自己的存储引擎,主要他们复合接口就行。

8.模型-视图-控制器 模型-视图-控制器又称为MVC模式,是描述应用程序3个不同层次之间关系的一种方式。 模型-数据层 所有的输出数据都来自模型。它可能是一个数据库、web服务或者文件。 视图-表现层 负责将数据从模型中取出并输出给用户。 控制器-应用程序流层 根据用户的请求调用相应的模型检索出请求的数据,然后调用视图将操作的结果显示给用户。

一个典型的MVC架构图: php mvc架构图

9.对模式的理解
模式是很多常见问题的最佳解决方法。

您可能感兴趣的文章:

  • php设计模式之单例模式、工厂模式与观察者模式
  • 深入php设计模式实例详解
  • php设计模式实例之命令模式
  • php设计模式实例之观察者模式(2)
  • PHP设计模式实例之观察者模式
  • php设计模式实例之工厂模式
  • php设计模式实例之单例模式
  • PHP设计模式之观察者模式的例子
  • php设计模式之工厂模式的实例代码
  • php设计模式之单例模式的实例代码
  • php常用设计模式之工厂模式与单例模式介绍
  • 学习php设计模式之单例模式
  • php常用的三种设计模式的学习笔记
  • php设计模式之单例模式学习


相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 生态工具与框架:扩展开发能力
Golang 生态工具与框架:扩展开发能力

《Golang 生态工具与框架》系统梳理 Go 语言在实际工程中的主流工具链与框架选型思路,涵盖 Web 框架、RPC 通信、依赖管理、测试工具、代码生成与项目结构设计等内容。通过真实项目场景解析不同工具的适用边界与组合方式,帮助开发者构建高效、可维护的 Go 工程体系,并提升团队协作与交付效率。

1

2026.02.24

Golang 性能优化专题:提升应用效率
Golang 性能优化专题:提升应用效率

《Golang 性能优化专题》聚焦 Go 应用在高并发与大规模服务中的性能问题,从 profiling、内存分配、Goroutine 调度、GC 机制到 I/O 与锁竞争逐层分析。结合真实案例讲解定位瓶颈的方法与优化策略,帮助开发者建立系统化性能调优思维,在保证代码可维护性的同时显著提升服务吞吐与稳定性。

2

2026.02.24

Golang 面试题精选:高频问题与解答
Golang 面试题精选:高频问题与解答

Golang 面试题精选》系统整理企业常见 Go 技术面试问题,覆盖语言基础、并发模型、内存与调度机制、网络编程、工程实践与性能优化等核心知识点。每道题不仅给出答案,还拆解背后的设计原理与考察思路,帮助读者建立完整知识结构,在面试与实际开发中都能更从容应对复杂问题。

1

2026.02.24

Golang 运行与部署实战:从本地到云端
Golang 运行与部署实战:从本地到云端

《Golang 运行与部署实战》围绕 Go 应用从开发完成到稳定上线的完整流程展开,系统讲解编译构建、环境配置、日志与配置管理、容器化部署以及常见运维问题处理。结合真实项目场景,拆解自动化构建与持续部署思路,帮助开发者建立可靠的发布流程,提升服务稳定性与可维护性。

3

2026.02.24

Golang 疑难杂症解决指南:常见问题排查与优化
Golang 疑难杂症解决指南:常见问题排查与优化

《Golang 疑难杂症解决指南》聚焦开发过程中常见却棘手的问题,从并发模型、内存管理、性能瓶颈到工程化实践逐步拆解。通过真实案例与调试思路,帮助开发者定位问题根因,建立系统化排查方法。不只给出答案,更强调分析路径与工具使用,让你在复杂 Go 项目中具备持续解决问题的能力。

1

2026.02.24

Golang 入门学习路线:从零基础到上手开发
Golang 入门学习路线:从零基础到上手开发

Golang 入门路线涵盖从零到上手的核心路径:首先打牢基础语法与切片等底层机制;随后攻克 Go 的灵魂——接口设计与 Goroutine 并发模型;接着通过 Gin 框架与 GORM 深入 Web 开发实战;最后在微服务与云原生工具开发中进阶,旨在培养具备高性能并发处理能力的后端工程师。

0

2026.02.24

中国研究生招生信息网官方网站入口 研招网网页版在线入口
中国研究生招生信息网官方网站入口 研招网网页版在线入口

中国研究生招生信息网入口(https://yz.chsi.com.cn) 此网站是研究生报名入口的唯一官方网站

95

2026.02.24

苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法
苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法

本专题汇总苹果官网最新可用入口及中国站点访问方式,涵盖官网直达链接、iPhone官方页面查看方法与常见访问说明,帮助用户快速进入苹果官方网站,便捷了解产品信息与官方服务。

14

2026.02.24

Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址
Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址

本专题系统整理Asianfanfics(AFF)官方网站最新可用入口,涵盖官方平台最新直达地址、官网登录方式及中文访问指引,帮助用户快速、安全地进入AFF平台浏览与使用相关内容。

15

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
第二十四期_PHP8编程
第二十四期_PHP8编程

共86课时 | 3.4万人学习

Laravel 8 课程精讲(台湾同胞版)
Laravel 8 课程精讲(台湾同胞版)

共22课时 | 2.4万人学习

第二十三期_PHP编程
第二十三期_PHP编程

共93课时 | 7.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号