美文网首页
PHP 设计模式 - 创建型 - 单例模式(Singleton)

PHP 设计模式 - 创建型 - 单例模式(Singleton)

作者: SylviaYuan95 | 来源:发表于2021-01-12 20:07 被阅读0次

1. 模式定义

单例设计模式(Singleton Design Pattern):一个类只允许创建一个对象(或者实例),那这个类就是单例类,这种设计模式就叫做单例设计模式,简称单例模式。
在整个应用程序的生命周期中,任何时刻,单例类仅存在一个实例,同时这个类还必须提供一个访问该类的全局访问点。 常见使用实例:数据库连接器;日志记录器(如果有多种用途使用多例模式);锁定文件。

2. UML类图

image.png

instance 翻译为实例

3. 示例代码

下面是项目开发中用到的一个存储当前用户信息的一个单例例子。需要注意是由于PHP是单线程,所以用户信息使用单例模式时,不会存在安全问题(问题指:多个用户登陆使用的是第一个实例化的用户信息),多注意单例的使用场景。
其UML类图如下:


image.png

具体代码如下:

<?php

namespace DesignPattern\Creational\Singleton;

class  CurrentUser
{
    private static $instance = null; //当前类的实例(私有)
    private static $token = ''; //当前用户的token值(私有)
    private static $userInfo = [];  //当前用户基本信息数组(私有)

    private function __construct($token, $userInfo)  //私有的构造方法,从而禁止从外部用 new 关键字创建实例(私有)
    {
        self::$token = $token;
        self::$userInfo = $userInfo;
    }

    private function __clone()   //克隆方法私有化,从而禁止从外部通过 clone 关键字创建实例(私有)
    {

    }

    public static function getInstance($token, $userInfo) //用于生成当前类的实例(公共)
    {
        //如果$instance变量中保存的不是当前类的实例
        if (!self::$instance instanceof self) {
            //那么就new一个当前类,并保存在$instance中
            self::$instance = new self($token, $userInfo);
        }
        //否则直接返回$instance
        return self::$instance;
    }

    public static function getToken() //用于获取当前用户 token
    {
        return self::$token;
    }

    public static function getUserInfo()  //用于获取当前用户信息数组 userInfo
    {
        return self::$userInfo;
    }
}

单元测试

<?php

namespace DesignPattern\Tests;

use DesignPattern\Creational\Singleton\CurrentUser;
use PHPUnit\Framework\TestCase;

/**
 * 测试单例模式
 * Class SingletonTest
 * @package Creational\Singleton\Tests
 */
class SingletonTest extends TestCase
{

    public function testUniqueness()
    {
        $firstCall = CurrentUser::getInstance('token1', ['name' => 'Sylvia', 'sex' => '女']);
        $firstUserInfo = $firstCall::getUserInfo();
        $this->assertInstanceOf(CurrentUser::class, $firstCall);
        $secondCall = CurrentUser::getInstance('token2', ['name' => 'Tom', 'sex' => '男']);
        $secondUserInfo = $secondCall::getUserInfo();
        $this->assertSame($firstCall, $secondCall);
        $this->assertSame($firstUserInfo, $secondUserInfo);
    }

    /**
     * @throws \ReflectionException
     */
    public function testNoConstructor()
    {
        $obj = CurrentUser::getInstance('token1', ['name' => 'Sylvia', 'sex' => '女']);

        $refl = new \ReflectionObject($obj);
        $meth = $refl->getMethod('__construct');
        $this->assertTrue($meth->isPrivate());
    }
}

此文章为学习笔记,学习文档如下:
学院君 : https://laravelacademy.org/post/2599
极客时间 : 设计模式之美
教程源码:https://github.com/SylviaYuan1995/DesignPatternDemo

相关文章

网友评论

      本文标题:PHP 设计模式 - 创建型 - 单例模式(Singleton)

      本文链接:https://www.haomeiwen.com/subject/cyyeaktx.html