欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-03-11 13:41:10
...

单例模式

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

  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模型
单例模式,工厂模式,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