PHP设计模式-原生单例模式

补充2022/03/12

  • 特点
    三私一公: 私有静态属性, 私有构造方法, 私有__clone()方法, 公有静态方法
    -实现
Class Test
{
    private static $_instace;
    private function __construct() {
        
    }
    private function __clone() {
        
    }
    
    public function test() {
        echo "test";
    }
    
    public static function getInstace()
    {
        if (self::$_instace == null) {
            self::$_instace = new Test();
        }
        
        return self::$_instace;
    }
}

$obj = Test::getInstace();
$obj->test();

单例模式

单例模式已经被考虑列入到反模式中!请使用依赖注入获得更好的代码可测试性和可控性!
单例模式通常情况下是内部实例化。

目标

使应用中只存在一个对象的实例,并且使这个单实例负责所有对该对象的调用。

例子

1、数据库连接器
2、日志记录器
3、应用锁文件 (理论上整个应用只有一个锁文件 …)

UML 图

在这里插入图片描述

代码
标准单例模式: HttpClient.php

1.创建一个静态私有变量存放实例化的对象
2.创建一个私有构造函数
3.防止外部克隆该类
4.防止序列化
5.提供唯一的静态入口(判断$instance变量是否是HttpClient类的实例,如果不是,则实例化本身,如果是则直接返回)

<?php

/**
 * @var HttpClient
 */
class HttpClient
{
    /**
     * @var 请求的路径
     */
    private $url;

    /**
     * @var 请求方式
     */
    private $method;

    /**
     * @var 请求参数
     */
    private $param;

    /**
     * @var 请求头
     */
    private $header;

    /**
     * @var 响应结果
     */
    private $response;

    //1.创建一个静态私有变量存放实例化的对象
    private static $instance;

    //2.创建一个私有构造函数
    private function __construct()
    {
    }
    //3.防止外部克隆该类
    private function __clone()
    {
    }
    //4.防止序列化
    private function __wakeup()
    {
    }
    //5.提供唯一的静态入口
    public static function getInstance()
    {
        //判断$instance变量是否是HttpClient类的实例,如果不是,则实例化本身,如果是则直接返回
        //instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例
        if(!(static::$instance instanceof static )){ //static 换成self也可以,只不过static比self更精准些
            static::$instance  = new static;
        }
        return static::$instance;
    }


    /**
     * @var 设置请求路径
     *
     * @param string url
     *
     * @return HttpClient
     */
    private function setUrl(String $url = '')
    {
        $this->url = $url;
        return $this;
    }

    /**
     * @var 设置请求参数
     *
     * @param array param
     *
     * @return HttpClient
     */
    private function setParam(Array $param)
    {
        $this->param = http_build_query($param);
        return $this;
    }

    /**
     * @var 设置请求头部
     *
     * @param array header
     *
     * @return HttpClient
     */
    private function setHeader(Array $header)
    {
        foreach ($header as $key => $value) {
            if (is_string($key)) {
                $key = constant(strtoupper($key));
            }

            $this->header[$key] = $value;
        }

        return $this;
    }

    /**
     * @var 设置请求方式
     *
     * @param string method
     *
     * @return HttpClient
     */
    private function setMethod(String $method = 'GET')
    {
        $this->method = $method;
        return $this;
    }

    /**
     * @var 开始请求
     *
     * @return HttpClient
     */
    private function exec()
    {
        $ch = curl_init();

        if ($this->header) {
            foreach ($this->header as $key => $value) {
                curl_setopt($ch, $key, $value);
            }
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_URL, $this->url);

        if ($this->method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $this->param);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/x-www-form-urlencoded; charset=utf-8',
                'Content-Length: ' . strlen($this->param)
            ));
        } elseif ($this->method == 'GET') {
            curl_setopt($ch, CURLOPT_URL, $this->url.'?'.$this->param);
            curl_setopt($ch, CURLOPT_HEADER, false);
        }

        $info = curl_getinfo($ch);
        $data = curl_exec($ch);
        $error = curl_errno($ch);
        curl_close($ch);

        $this->response = [
            'code' => $error ? 1 : 0,
            'message' => $error,
            'info' => $info,
            'data' => $data,
        ];
        return $this;
    }

    /**
     * @var 获取响应数据
     *
     * @throw Exception
     *
     * @return array|string
     */
    public function getBody()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['data'];
    }

    /**
     * @var 获取响应状态码
     *
     * @throw Exception
     *
     * @return int
     */
    public function getCode()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['code'];
    }

    /**
     * @var 获取错误信息
     *
     * @throw Exception
     *
     * @return int|array
     */
    public function getMessage()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['message'];
    }

    /**
     * @var 获取响应信息
     *
     * @return array
     */
    public function getInfo()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['info'];
    }

    /**
     * @var GET请求
     *
     * @param string url
     * @param array param
     * @param array header
     *
     * @return HttpClient
     */
    public function get(String $url, Array $param = [], Array $header = [])
    {
        return $this->setMethod('GET')->setUrl($url)->setParam($param)->setHeader($header)->exec();
    }

    /**
     * @var POST请求
     *
     * @param string url
     * @param array param
     * @param array header
     *
     * @return HttpClient
     */
    public function post(String $url, Array $param = [], $header = [])
    {
        return $this->setMethod('POST')->setUrl($url)->setParam($param)->setHeader($header)->exec();
    }

    /**
     * @var 清理垃圾
     */
    public function __destruct()
    {
        $this->url = null;
        $this->method = null;
        $this->param = null;
        $this->header = null;
        $this->response = null;
    }
}

调用

<?php
require './inside/HttpClient.php';

$obj1 = HttpClient::getInstance();
$obj2 = HttpClient::getInstance();
var_dump($obj1 === $obj2);

显示结果
在这里插入图片描述

外部调用单例模式:也就是代理模式(TP5.1facade)

单例类:
1.防止外部克隆该类
2.防止序列化

代理类:
1.引用单例类,在代理类中实例化单例类
2.通过静态调用代理类从而使用单例类

单例类

<?php

/**
 * @var HttpClient
 */
class HttpClient
{
    /**
     * @var 请求的路径
     */
    private $url;

    /**
     * @var 请求方式
     */
    private $method;

    /**
     * @var 请求参数
     */
    private $param;

    /**
     * @var 请求头
     */
    private $header;

    /**
     * @var 响应结果
     */
    private $response;

    //1.防止外部克隆该类
    private function __clone()
    {
    }
    //2.防止序列化
    private function __wakeup()
    {
    }

    /**
     * @var 设置请求路径
     *
     * @param string url
     *
     * @return HttpClient
     */
    private function setUrl(String $url = '')
    {
        $this->url = $url;
        return $this;
    }

    /**
     * @var 设置请求参数
     *
     * @param array param
     *
     * @return HttpClient
     */
    private function setParam(Array $param)
    {
        $this->param = http_build_query($param);
        return $this;
    }

    /**
     * @var 设置请求头部
     *
     * @param array header
     *
     * @return HttpClient
     */
    private function setHeader(Array $header)
    {
        foreach ($header as $key => $value) {
            if (is_string($key)) {
                $key = constant(strtoupper($key));
            }

            $this->header[$key] = $value;
        }

        return $this;
    }

    /**
     * @var 设置请求方式
     *
     * @param string method
     *
     * @return HttpClient
     */
    private function setMethod(String $method = 'GET')
    {
        $this->method = $method;
        return $this;
    }

    /**
     * @var 开始请求
     *
     * @return HttpClient
     */
    private function exec()
    {
        $ch = curl_init();

        if ($this->header) {
            foreach ($this->header as $key => $value) {
                curl_setopt($ch, $key, $value);
            }
        }

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_URL, $this->url);

        if ($this->method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $this->param);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/x-www-form-urlencoded; charset=utf-8',
                'Content-Length: ' . strlen($this->param)
            ));
        } elseif ($this->method == 'GET') {
            curl_setopt($ch, CURLOPT_URL, $this->url.'?'.$this->param);
            curl_setopt($ch, CURLOPT_HEADER, false);
        }

        $info = curl_getinfo($ch);
        $data = curl_exec($ch);
        $error = curl_errno($ch);
        curl_close($ch);

        $this->response = [
            'code' => $error ? 1 : 0,
            'message' => $error,
            'info' => $info,
            'data' => $data,
        ];
        return $this;
    }

    /**
     * @var 获取响应数据
     *
     * @throw Exception
     *
     * @return array|string
     */
    public function getBody()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['data'];
    }

    /**
     * @var 获取响应状态码
     *
     * @throw Exception
     *
     * @return int
     */
    public function getCode()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['code'];
    }

    /**
     * @var 获取错误信息
     *
     * @throw Exception
     *
     * @return int|array
     */
    public function getMessage()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['message'];
    }

    /**
     * @var 获取响应信息
     *
     * @return array
     */
    public function getInfo()
    {
        if (!$this->response) {
            throw new Exception('no httpRequest');
        }

        return $this->response['info'];
    }

    /**
     * @var GET请求
     *
     * @param string url
     * @param array param
     * @param array header
     *
     * @return HttpClient
     */
    public function get(String $url, Array $param = [], Array $header = [])
    {
        return $this->setMethod('GET')->setUrl($url)->setParam($param)->setHeader($header)->exec();
    }

    /**
     * @var POST请求
     *
     * @param string url
     * @param array param
     * @param array header
     *
     * @return HttpClient
     */
    public function post(String $url, Array $param = [], $header = [])
    {
        return $this->setMethod('POST')->setUrl($url)->setParam($param)->setHeader($header)->exec();
    }

    /**
     * @var 清理垃圾
     */
    public function __destruct()
    {
        $this->url = null;
        $this->method = null;
        $this->param = null;
        $this->header = null;
        $this->response = null;
    }
}

代理类

<?php
include 'D:\phpstudy_pro\WWW\project\singleton\outside\HttpClient.php';

class Singleton
{
    private static $httpclicent;

    public static function httpclient()
    {
        if (!(static::$httpclicent instanceof static)){  
            static::$httpclicent = new static;
        }
        return static::$httpclicent;
    }
}

使用

require './outside/Singleton.php';

$obj1 = Singleton::httpclient();
$obj2 = Singleton::httpclient();
var_dump($obj1 === $obj2);

结果页面
在这里插入图片描述

参考文档:
https://designpatternsphp.readthedocs.io/zh_CN/latest/Creational/Singleton/README.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值