介绍
创建对象中,单例模式确保某个类只有一个实例,并且会自己实例化向外提供这个示例.例如在使用单例模式操作数据库的时候可以避免大量的连接数据库消耗资源,减少数据库连接.
当需要单例模式的对象直接调用getInstanc()
获取之前实例化的对象,不需要重新实例化对象.当一个对象需要频繁的创建销毁,而性能又无法优化的情况下使用单例模式是非常节省资源.
特点
- 私有构造方法(防止其他类实例化)
- 私有克隆方法(防止克隆生成对象)
- 私有静态属性(防止篡改,存储实例)
- 公有静态方法(调取类相于一个接口)
优缺点
优点
- 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例.
- 避免对资源的多重占用.
缺点
没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化.
演示
单例模式Redis
<?php
namespace Tools;
class Redis
{
static private $redis;
private static $instance;
private function __construct($host,$port)
{
self::$redis = new \Redis();
self::$redis->connect($host, $port);
}
static public function getInstance(...$args)
{
if (!isset(self::$instance)) {
self::$instance = new static(...$args);
}
return self::$instance;
}
public function __call($name, $arguments)
{
return self::$redis->$name(...$arguments);
}
}
使用
<?php
namespace App\Controller\User;
class Login
{
static function success()
{
echo '登录成功' . PHP_EOL;
}
static function getUser()
{
$user = isset($_GET['user'])?$_GET['user']:'angel';
$getUserName = \Tools\Redis::getInstance('127.0.0.1',6379)->get($user);
print_r($getUserName);
}
}
完善
使用trait
将getInstance
方法抽离出去.每当使用单例模式的时候直接use trait
即可.
创建Tools/Singleton.php
<?php
namespace Tools;
trait Singleton
{
private static $instance;
static function getInstance(...$args)
{
if(!isset(self::$instance)){
self::$instance = new static(...$args);
}
return self::$instance;
}
}
修改Tools/Redis.php
使用use Singleton;
替换instance
成员属性和方法,__construct
的比穿参数可以去掉,直接在连接的时候写上值或者通过Yaconf
获取配置信息连接.不需要在调用的时候.
<?php
namespace Tools;
class Redis
{
use Singleton;
static private $redis;
private function __construct()
{
self::$redis = new \Redis();
self::$redis->connect('127.0.0.1', 6379);
}
public function __call($name, $arguments)
{
return self::$redis->$name(...$arguments);
}
}
使用
<?php
class Login
{
static function success()
{
echo '登录成功' . PHP_EOL;
}
static function getUser()
{
$user = isset($_GET['user'])?$_GET['user']:'sms_15032061937';
$getUserName = \Tools\Redis::getInstance()->get($user);
print_r($getUserName);
}
}