单例模式,工厂模式,MVC初学
程序员文章站
2022-03-11 13:41:10
...
单例模式
单例模式就是实现一个类只能实例化一次,不允许实例化多次
<?php
class Demo
{
private static $instance = null; // 用这个属性保存实例化后的对象
// 禁止外部用 new 实例化类,只需要将构造方法私有化即可
private function __construct(...$args)
{
print_r($args); // 将参数打印出来看看
}
// 禁止外部克隆出对象,将clone方法私有化
private function __clone()
{
}
// 用这个方法来实例化
public static function getInstance(...$args)
{
if (is_null(self::$instance)) {
return self::$instance = new self(...$args);
}
return self::$instance;
}
}
// 这里执行多次实例化,会发现每次执行返回的都是同一个对象,
// 而参数也只会被打印一次,因为第一次实例化后,后面的实例化其实都不会执行
var_dump(Demo::getInstance(1,2));
var_dump(Demo::getInstance(3,4));
var_dump(Demo::getInstance(5,6));
工厂模式
就是用一个类将实例化过程给独立出来
即在一个类中实现 实例化一个类并返回实例对象 的方法
namespace day1011;
class Test1 {
public function __construct(...$args)
{
echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
}
}
class Test2 {
public function __construct(...$args)
{
echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
}
}
class Test3 {
public function __construct(...$args)
{
echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
}
}
class Test4 {
public function __construct(...$args)
{
echo '这是'.__CLASS__.'实例化的对象,参数为'***plode(', ',$args).'<br/>';
}
}
// 将工厂设计成接口类
interface iFactory {
public static function make($className, ...$args);
}
// 将工厂设计成抽象类
abstract class aFactory
{
abstract static function make($className, ...$args);
}
// class Factory extends aFactory {
// public static function make($className, ...$args) {
// return new $className(...$args);
// }
// }
class Factory implements iFactory {
public static function make($className, ...$args) {
return new $className(...$args);
}
}
Factory::make(Test1::class,1,2);
Factory::make(Test2::class,3,4);
Factory::make(Test3::class,5,6);
MVC—依赖注入
MVC模式是很常见的一种设计思想:即将数据,视图与控制器分开
M: Model, 模型, 数据, 主要针对的是数据库的操作, CURD
V: View, 视图, html文档,浏览器用户看到内容/页面
C: Controller, 控制器, 模型和视图都必须在控制器中调用
这里来建立一个简单 MVC 案例
Model.php
<?php
/**
* 数据库模型类
*/
class Model
{
protected $pdo = null;
protected $where;
public function __construct()
{
$this->pdo = new \PDO('mysql:host=127.0.0.1;dbname=zmx','root','root');
}
// 获取数据
public function getData($where){
$this->where = empty($where) ? '' : ' WHERE '.$where;
$sql = 'SELECT * FROM `staff`'.$this->where;
$stmt = $this->pdo->prepare($sql);
if($stmt->execute()){
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}else {
print_r('呵呵');
die($stmt->errorInfo());
}
}
}
View.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="table.css">
</head>
<body>
<div>
<?php
/**
* 视图
*/
class View {
// 定义一个渲染表格方法
public function render($data){
$table = '<table border="1" cellpadding="0" cellspacing="0" width="400">';
$table .= '<caption>人员表</caption>';
$table .= '<tr><th>ID</th><th>姓名</th><th>年龄</th><th>性别</th><th>职位</th></tr>';
foreach ($data as $person) {
$table .= '<tr>';
$table .= '<td>' . $person['staff_id'] . '</td>';
$table .= '<td>' . $person['name'] . '</td>';
$table .= '<td>' . $person['age'] . '</td>';
$table .= '<td>' . ($person['sex'] == 1 ? '男' : '女') . '</td>';
$table .= '<td>' . $person['position'] . '</td>';
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
Controller.php
<?php
/**
* 控制类
* 依赖注入
*/
require 'Model.php';
require 'View.php';
class Controller {
public function renderIndex($model, $view){
$data = $model->getData('age >40');
return $view->render($data);
}
}
$model = new Model();
$view = new View();
$controller = new Controller();
// 依赖注入
// 将模型对象和视图对象作为参数传入
echo $controller->renderIndex($model, $view);
这样就简单实现了一个mvc模型
改进一下:加入服务容器和门面模式
<?php
/**
* 控制器
* 服务容器(简称为容器),将对象的创建与使用过程统一管理起来
* 门面模式,又叫外观模式,静态代理,就是将所有调用的代码静态化,就是给调用方法再包一层
*/
require 'Model.php';
require 'View.php';
// 门面模式
// 给方法再再套个马甲
class Facade
{
protected static $container = null;
protected static $data = [];
public static function initialize($container)
{
static::$container = $container;
}
public static function getData($where)
{
static::$data = static::$container->generate('Model')->getData($where);
}
public static function render(){
return static::$container->generate('View')->render(static::$data);
}
}
// 建议一个服务容器类
class Container
{
// 声明一个数组,存放 类名 => 方法
protected $instance = [];
// 向数组中存储数据
public function bind($className, Closure $process)
{
$this->instance[$className] = $process;
}
// 执行数组中对应方法
public function generate($className, ...$args)
{
// 采用回调函数执行对应犯法数组中对应的函数
return call_user_func_array($this->instance[$className], $args);
}
}
$container = new Container();
$container->bind('Model', function () {
return new Model;
});
$container->bind('View', function () {
return new View;
});
class Controller
{
public function __construct($container)
{
Facade::initialize($container);
}
public function renderIndex()
{
Facade::getData('age>20');
return Facade::render();
}
}
$controller = new Controller($container);
echo $controller->renderIndex();
路由
** 路由其实就是解析页面路径,通过解析后的数据来执行不同操作。
<?php
/**
* 路由
*/
解析已下路由:规定此路径:大概规则是 .../模块名/控制器名/方法?参数
//http://zx.com/day1011/route.php/admin/user/get?id=3&&age=20
$url = $_SERVER['REQUEST_URI']; // 获取路由
echo $url;
$req = explode('/', $url);
echo '<pre>'.print_r($req,true);
// 模块/控制器/方法
// 将 url中的方法解析出来,映射到对应的函数上
// 取模块
$module = array_slice($req, -3,1)[0];
// 取控制器
$controller = array_slice($req, -2,1)[0];
// 取方法
$last = array_slice($req, -1,1);
$method = explode('?', $last[0])[0];
$values = explode('?', $last[0])[1];
// 取参数
$params = explode('&', $values);
$paramsArr = [];
foreach($params as $val){
$name = explode('=', $val)[0];
$value = explode('=', $val)[1];
$paramsArr[$name] = $value;
}
print_r($paramsArr);
echo '模块:'.$module.'<br/>';
echo '控制器:'.$controller.'<br/>';
echo '方法:'.$method.'<br/>';
echo '参数:<pre>'.print_r($paramsArr,true);
// 控制器
// 路由的目标, 就是将URL中的操作映射到控制器中的方法上
class User
{
public function get($id, $age)
{
return 'ID为'.$id.'的用户年龄为'.$age;
}
}
// 将路由解析到的数据进行传入到对应的方法
echo call_user_func_array([(new User()), $method], $params);
最终输出: ID为id=3的用户年龄为age=20