博客列表 >单例模式,工厂模式,MVC初学

单例模式,工厂模式,MVC初学

小星的博客
小星的博客原创
2019年12月03日 01:56:051102浏览

单例模式

单例模式就是实现一个类只能实例化一次,不允许实例化多次

  1. <?php
  2. class Demo
  3. {
  4. private static $instance = null; // 用这个属性保存实例化后的对象
  5. // 禁止外部用 new 实例化类,只需要将构造方法私有化即可
  6. private function __construct(...$args)
  7. {
  8. print_r($args); // 将参数打印出来看看
  9. }
  10. // 禁止外部克隆出对象,将clone方法私有化
  11. private function __clone()
  12. {
  13. }
  14. // 用这个方法来实例化
  15. public static function getInstance(...$args)
  16. {
  17. if (is_null(self::$instance)) {
  18. return self::$instance = new self(...$args);
  19. }
  20. return self::$instance;
  21. }
  22. }
  23. // 这里执行多次实例化,会发现每次执行返回的都是同一个对象,
  24. // 而参数也只会被打印一次,因为第一次实例化后,后面的实例化其实都不会执行
  25. var_dump(Demo::getInstance(1,2));
  26. var_dump(Demo::getInstance(3,4));
  27. var_dump(Demo::getInstance(5,6));

工厂模式

就是用一个类将实例化过程给独立出来
即在一个类中实现 实例化一个类并返回实例对象 的方法

  1. namespace day1011;
  2. class Test1 {
  3. public function __construct(...$args)
  4. {
  5. echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
  6. }
  7. }
  8. class Test2 {
  9. public function __construct(...$args)
  10. {
  11. echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
  12. }
  13. }
  14. class Test3 {
  15. public function __construct(...$args)
  16. {
  17. echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
  18. }
  19. }
  20. class Test4 {
  21. public function __construct(...$args)
  22. {
  23. echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
  24. }
  25. }
  26. // 将工厂设计成接口类
  27. interface iFactory {
  28. public static function make($className, ...$args);
  29. }
  30. // 将工厂设计成抽象类
  31. abstract class aFactory
  32. {
  33. abstract static function make($className, ...$args);
  34. }
  35. // class Factory extends aFactory {
  36. // public static function make($className, ...$args) {
  37. // return new $className(...$args);
  38. // }
  39. // }
  40. class Factory implements iFactory {
  41. public static function make($className, ...$args) {
  42. return new $className(...$args);
  43. }
  44. }
  45. Factory::make(Test1::class,1,2);
  46. Factory::make(Test2::class,3,4);
  47. Factory::make(Test3::class,5,6);

MVC—依赖注入

MVC模式是很常见的一种设计思想:即将数据,视图与控制器分开
M: Model, 模型, 数据, 主要针对的是数据库的操作, CURD
V: View, 视图, html文档,浏览器用户看到内容/页面
C: Controller, 控制器, 模型和视图都必须在控制器中调用

这里来建立一个简单 MVC 案例

Model.php

  1. <?php
  2. /**
  3. * 数据库模型类
  4. */
  5. class Model
  6. {
  7. protected $pdo = null;
  8. protected $where;
  9. public function __construct()
  10. {
  11. $this->pdo = new \PDO('mysql:host=127.0.0.1;dbname=zmx','root','root');
  12. }
  13. // 获取数据
  14. public function getData($where){
  15. $this->where = empty($where) ? '' : ' WHERE '.$where;
  16. $sql = 'SELECT * FROM `staff`'.$this->where;
  17. $stmt = $this->pdo->prepare($sql);
  18. if($stmt->execute()){
  19. return $stmt->fetchAll(\PDO::FETCH_ASSOC);
  20. }else {
  21. print_r('呵呵');
  22. die($stmt->errorInfo());
  23. }
  24. }
  25. }

View.php

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <link rel="stylesheet" href="table.css">
  6. </head>
  7. <body>
  8. <div>
  9. <?php
  10. /**
  11. * 视图
  12. */
  13. class View {
  14. // 定义一个渲染表格方法
  15. public function render($data){
  16. $table = '<table border="1" cellpadding="0" cellspacing="0" width="400">';
  17. $table .= '<caption>人员表</caption>';
  18. $table .= '<tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>职位</th></tr>';
  19. foreach ($data as $person) {
  20. $table .= '<tr>';
  21. $table .= '<td>' . $person['staff_id'] . '</td>';
  22. $table .= '<td>' . $person['name'] . '</td>';
  23. $table .= '<td>' . $person['age'] . '</td>';
  24. $table .= '<td>' . ($person['sex'] == 1 ? '男' : '女') . '</td>';
  25. $table .= '<td>' . $person['position'] . '</td>';
  26. $table .= '</tr>';
  27. }
  28. $table .= '</table>';
  29. return $table;
  30. }
  31. }

Controller.php

  1. <?php
  2. /**
  3. * 控制类
  4. * 依赖注入
  5. */
  6. require 'Model.php';
  7. require 'View.php';
  8. class Controller {
  9. public function renderIndex($model, $view){
  10. $data = $model->getData('age >40');
  11. return $view->render($data);
  12. }
  13. }
  14. $model = new Model();
  15. $view = new View();
  16. $controller = new Controller();
  17. // 依赖注入
  18. // 将模型对象和视图对象作为参数传入
  19. echo $controller->renderIndex($model, $view);

这样就简单实现了一个mvc模型

改进一下:加入服务容器和门面模式

  1. <?php
  2. /**
  3. * 控制器
  4. * 服务容器(简称为容器),将对象的创建与使用过程统一管理起来
  5. * 门面模式,又叫外观模式,静态代理,就是将所有调用的代码静态化,就是给调用方法再包一层
  6. */
  7. require 'Model.php';
  8. require 'View.php';
  9. // 门面模式
  10. // 给方法再再套个马甲
  11. class Facade
  12. {
  13. protected static $container = null;
  14. protected static $data = [];
  15. public static function initialize($container)
  16. {
  17. static::$container = $container;
  18. }
  19. public static function getData($where)
  20. {
  21. static::$data = static::$container->generate('Model')->getData($where);
  22. }
  23. public static function render(){
  24. return static::$container->generate('View')->render(static::$data);
  25. }
  26. }
  27. // 建议一个服务容器类
  28. class Container
  29. {
  30. // 声明一个数组,存放 类名 => 方法
  31. protected $instance = [];
  32. // 向数组中存储数据
  33. public function bind($className, Closure $process)
  34. {
  35. $this->instance[$className] = $process;
  36. }
  37. // 执行数组中对应方法
  38. public function generate($className, ...$args)
  39. {
  40. // 采用回调函数执行对应犯法数组中对应的函数
  41. return call_user_func_array($this->instance[$className], $args);
  42. }
  43. }
  44. $container = new Container();
  45. $container->bind('Model', function () {
  46. return new Model;
  47. });
  48. $container->bind('View', function () {
  49. return new View;
  50. });
  51. class Controller
  52. {
  53. public function __construct($container)
  54. {
  55. Facade::initialize($container);
  56. }
  57. public function renderIndex()
  58. {
  59. Facade::getData('age>20');
  60. return Facade::render();
  61. }
  62. }
  63. $controller = new Controller($container);
  64. echo $controller->renderIndex();

路由

** 路由其实就是解析页面路径,通过解析后的数据来执行不同操作。

  1. <?php
  2. /**
  3. * 路由
  4. */
  5. 解析已下路由:规定此路径:大概规则是 .../模块名/控制器名/方法?参数
  6. //http://zx.com/day1011/route.php/admin/user/get?id=3&&age=20
  7. $url = $_SERVER['REQUEST_URI']; // 获取路由
  8. echo $url;
  9. $req = explode('/', $url);
  10. echo '<pre>'.print_r($req,true);
  11. // 模块/控制器/方法
  12. // 将 url中的方法解析出来,映射到对应的函数上
  13. // 取模块
  14. $module = array_slice($req, -3,1)[0];
  15. // 取控制器
  16. $controller = array_slice($req, -2,1)[0];
  17. // 取方法
  18. $last = array_slice($req, -1,1);
  19. $method = explode('?', $last[0])[0];
  20. $values = explode('?', $last[0])[1];
  21. // 取参数
  22. $params = explode('&', $values);
  23. $paramsArr = [];
  24. foreach($params as $val){
  25. $name = explode('=', $val)[0];
  26. $value = explode('=', $val)[1];
  27. $paramsArr[$name] = $value;
  28. }
  29. print_r($paramsArr);
  30. echo '模块:'.$module.'<br/>';
  31. echo '控制器:'.$controller.'<br/>';
  32. echo '方法:'.$method.'<br/>';
  33. echo '参数:<pre>'.print_r($paramsArr,true);
  34. // 控制器
  35. // 路由的目标, 就是将URL中的操作映射到控制器中的方法上
  36. class User
  37. {
  38. public function get($id, $age)
  39. {
  40. return 'ID为'.$id.'的用户年龄为'.$age;
  41. }
  42. }
  43. // 将路由解析到的数据进行传入到对应的方法
  44. echo call_user_func_array([(new User()), $method], $params);

最终输出: ID为id=3的用户年龄为age=20

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议