必须先声明一个静态私有属性:用来保存当前类的实例
* 1. 为什么必须是静态的?因为静态成员属于类,并被类的所有实例所共享 * 2. 为什么必须是私有的?不允许外部直接访问,仅允许通过类方法控制方法 * 3. 为什么要有初始值null,因为类内部访问接口需要检测实例的状态,判断是否需要实例化
//单例 class Uni{ //创建静态私有的变量保存该类对象 static private $instance; //参数 private $config; //防止直接创建对象 private function __construct($config){ $this -> config = $config; echo "我被实例化了"; } //防止克隆对象 private function __clone(){ } static public function getInstance($config){ //判断$instance是否是Uni的对象 //没有则创建 if (!self::$instance instanceof self) { self::$instance = new self($config); } return self::$instance; } public function getName(){ echo $this -> config; } } $db1 = Uni::getInstance(1); $db1 -> getName(); echo "<br>"; $db2 = Uni::getInstance(4); $db2 -> getName();
构造函数设置为私有属性的时候,只会触发一次?!构造函数是在类实例化的时候触发。构造方法不能声明为static 。静态方法不能调用非静态的方法。 非静态方法是可以调用静态方法的。
原因:静态方法是属于类的,即静态方法是随着类的加载而加载的,在加载类时,程序就会为静态方法分配内存。非静态方法是属于对象的,对象是在类加载之后创建的。也就是说静态方法先于对象存在,当你创建一个对象时,程序为其分配内存,一般是通过this指针来指向该对象。静态方法不依赖于对象的调用,它是通过‘类名.静态方法名’这样的方式来调用的。而对于非静态方法,在对象创建的时候程序才会为其分配内存,然后通过类的对象去访问非静态方法。在对象未存在时非静态方法也不存在,静态方法自然不能调用一个不存在的方法。
但是非静态方法也有办法调用静态方法: (new self())->func(); 类似这种。static 关键字除了可以声明类的静态成员(属性和方法)外,还有一个非常重要的作用就是后期静态绑定。
class Test { public function func () { return 'hello' ; } public static function action () { // 如何调用 func 方法 ? return (new self())->func(); } }
class Config1 {} class Config { private static $instance = null; //保存用户的自定义配置参数 private $setting = []; //构造器私有化:禁止从类外部实例化 private function __construct(){} //克隆方法私有化:禁止从外部克隆对象 private function __clone(){} //因为用静态属性返回类实例,而只能在静态方法使用静态属性 //所以必须创建一个静态方法来生成当前类的唯一实例 public static function getInstance() { //检测当前类属性$instance是否已经保存了当前类的实例 if (self::$instance == null) { //如果没有,则创建当前类的实例 self::$instance = new self(); } //如果已经有了当前类实例,就直接返回,不要重复创建类实例 return self::$instance; } //设置配置项 public function set($index, $value) { $this->setting[$index] = $value; } //读取配置项 public function get($index) { return $this->setting[$index]; } } $obj1 = new Config1; $obj2 = new Config1; var_dump($obj1,$obj2); echo '<hr>'; //实例化Config类 $obj1 = Config::getInstance(); $obj2 = Config::getInstance(); var_dump($obj1,$obj2); $obj1->set('host','localhost'); echo $obj1->get('host');
一、什么是单例模式 作为对象的创建模式,单例模式确保某一个类只有一个实例,并且对外提供这个全局实例的访问入口。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。
二、PHP单例模式三要素 1. 需要一个保存类的唯一实例的静态成员变量。 2. 构造函数和克隆函数必须声明为私有的,防止外部程序创建或复制实例副本。 3. 必须提供一个访问这个实例的公共静态方法,从而返回唯一实例的一个引用。
三、为什么使用单例模式 使用单例模式的好处很大,以数据库操作为例。若不采用单例模式,当程序中出现大量数据库操作时,每次都要执行new操作,
每次都会消耗大量的内存资源和系统资源,而且每次打开和关闭数据库连接都是对数据库的一种极大考验和浪费。使用了单例模式,只需要实例化一次,不需要每次都执行
new操作,极大降低了资源的耗费。
参考:https://www.cnblogs.com/sgm4231/p/9851725.html
突然有个小的疑问:为什么要把单例模式中的构造方法设置为私有呢?我测试把构造设为public好像没什么问题啊?
class Too { private static $instance ; public function __construct() { echo '构造---'; } public static function getInstance() { if(self::$instance === null){ self::$instance = new memcache; self::$instance -> connect('localhost',11211); } var_dump (self::$instance); } public function test() { var_dump(self::$instance); var_dump($this); } private function __clone() { // } } Too::getInstance(); $too = new Too; $too->getInstance(); $too1 = new Too; $too1->getInstance(); /*不明白为什么构造方法必须要设置成私有的,我这个测试设置为public,也能实现单例啊,哪里不对吗?而且把构造 方法设置为私有,那还怎么调用他啊?*/