美文网首页
单例模式

单例模式

作者: PENG先森_晓宇 | 来源:发表于2020-02-12 15:43 被阅读0次

    概念

    单例模式 (Singleton Pattern),是一种常用的软件设计模式。通过单例模式可以保证系统中一个类仅有一个对象实例

    1. 构造函数是私有的:仅供内部初始化时创建
    2. 定义该类的静态私有对象:instance变量
    3. 定义一个静态的公有的函数:用于初始化或获取它本身的静态私有对象
    4. 禁止拷贝对象:重写__clone(),里面空实现

    应用场景

    资源共享的情况下,会使用单例模式,避免由于资源操作时导致的性能或损耗等。通常服务类型的可以设置成单例,如mysql,redis,kafka,rabbitmq等。

    先上代码,是一个redis实例化的例子

    <?php
    
    namespace App\learn;
    
    use Predis\Client;
    
    class Redis
    {
    
        private static $instance;
    
        private static $host;
    
        private static $port;
    
        private function __construct($host, $port)
        {
            self::$host = $host;
            self::$port = $port;
            return new Client($host, $port);
        }
    
        public static function getInstance($host, $port)
        {
            if (!self::$instance instanceof self) {
                self::$instance = new self($host, $port);
            }
            return self::$instance;
        }
    
        /**
         * 禁止克隆
         */
        private function __clone()
        {
        }
    }
    
    $redis = Redis::getInstance('192.168.43.243', 6379);
    

    需要明白几个知识点

    • instance变量为什么是private和static?
      instance变量是用于getInstance方法返回redis实例的,所以该变量不需要外部访问,定义成private即可。
      静态成员是类属性。传统php-fpm模式下,在一次请求中,无论类实例化多少次,类中的静态成员是不会重置的,是驻内存的,在请求结束后,内存释放,变量也就释放。如果在swoole,java等编译型语言中,静态成员是在第一次调用后就会常驻内存的,也就是该静态成员是不会随着每次请求而释放的,所以单例在常驻内存的语言中是很有优势的。那么在传统php中是不是就没什么意义了呢?在多次请求的角度肯定没意义的,我们站在单次请求的角度出发,如果一次请求中有多次类实例化,此时如果使用单例模式的话可以避免多次实例造成资源浪费,毕竟单例模式就是保证系统中类只有一个实例化对象,避免造成资源浪费。
    • 构造函数为什么是private?
      因为实例化redis,我们只希望在getInstance中实例化,如果用户想获得redis实例调用getInstance方法即可,我们并不希望用户在外部可以直接new redis()。只要把构造函数设置成private即可实现上述。
    • getInstance方法为什么是public和static?
      首先getInstance方法是外部用户调用redis实例的方法,既然外部可以调用肯定是public修饰符。
      由于获取redis实例是通过外部调用getInstance方法来实现的,而此时我们构造方法又是private修饰符,所以如果想实现外部可以调用getInstance方法,我们只能将该getInstance方法设置成静态的,这样用户直接使用类::getInstance()的方式来获取类的实例了。
    • __clone()为什么设置成private
      首先__clone()是一个魔术方法,_clone()魔术方法只是在对象被克隆时会触发的方法。任何对象都是可以使用关键字clone来克隆的。
    $home = new Home();
    $cloneHome = clone $home;
    

    如果将__clone魔术方法设置成private,则代码禁止克隆,上述代码在使用关键字clone时就会提示错误。

    相关文章

      网友评论

          本文标题:单例模式

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