zoukankan      html  css  js  c++  java
  • php设计模式-单例模式

    <?php
    //简单的单例
    class Singleleton {
        private static $_instance = null;
    
        public static function getSingleleton()
        {
            if (isset(self::$_instance)) {
                return self::$_instance;
            }
    
            return new self();
        }
    }
    
    $instance1 = new Singleleton();
    $instance2 = Singleleton::getSingleleton();
    // var_dump($instance1);
    // var_dump($instance2);
    
    /*
        结果:object(Singleleton)#1 (0) { } object(Singleleton)#2 (0) { }
        问题:不能防止new实例化
    */
    
    // 改进1:封锁new 操作
    class Singleleton_1 {
        protected static $_instance = null; // 把自己的实例放在自己的一个静态属性上
    
        public static function getSingleleton()
        {
            if (isset(self::$_instance)) {
                return self::$_instance;
            }
            
            return new self();
        }
    
        protected function __construct(){}
    }
    
    // $instance1 = new Singleleton_1();
    // $instance2 = Singleleton_1::getSingleleton();
    // var_dump($instance1);
    // var_dump($instance2);
    
    /* 
        结果:Fatal error: Uncaught Error: Call to protected Singleleton_1::__construct() from invalid context
        结论:将构造方法设置为受保护阻止以new形式格式化
        问题: 一个类继承该类,并且使用public修饰的构造方法覆盖了父方法,则封锁__construct失败
    */
    
    class Child extends Singleleton_1
    {
        public function __construct()
        {
            
        }
    }
    
    $ins1 = new Child;
    $ins2 = new Child;
    
    // 这里用== 会得到true, 所以用===
    echo $ins1 === $ins2 ? '同一个实例' : '不同实例';
    
    /* 
        结果:不同实例
    */
    
    // 改进2:使用final禁止覆盖构造方法
    class Singleleton_2 {
        protected static $_instance = null; // 把自己的实例放在自己的一个静态属性上
    
        public static function getSingleleton()
        {
            if (isset(self::$_instance)) {
                return self::$_instance;
            }
            
            return new self();
        }
    
        // 当方法加final修饰,表示继承不能被覆盖,类加final表示不能被继承
        protected final function __construct(){} 
    }
    
    // class Child_2 extends Singleleton_2
    // {
    //     public function __construct()
    //     {
            
    //     }
    // }
    
    /**
     * 结果:Fatal error: Cannot override final method Singleleton_2::__construct()
     * 结论:能防止方法覆盖,导致单例失效
     * 问题:不能防止克隆,导致不同实例
     */
    
    
     // 改进3: 防止克隆
     class Singleleton_3 {
        protected static $_instance = null; // 把自己的实例放在自己的一个静态属性上
    
        public static function getSingleleton()
        {
            if (isset(self::$_instance)) {
                return self::$_instance;
            }
            
            return new self();
        }
    
        // 当方法加final修饰,表示继承不能被覆盖,类加final表示不能被继承
        protected final function __construct(){} 
    }
    
    $ins1 = Singleleton_3::getSingleleton();
    $ins2 = clone $ins1;
    
    echo $ins1 === $ins2 ? '同一个实例' : '不同实例'; // 不同实例
    
    class Singleleton_4 {
        protected static $_instance = null; // 把自己的实例放在自己的一个静态属性上
    
        public static function getSingleleton()
        {
            if (isset(self::$_instance)) {
                return self::$_instance;
            }
            
            return new self();
        }
    
        // 当方法加final修饰,表示继承不能被覆盖,类加final表示不能被继承
        protected final function __construct(){} 
    
        // 封锁克隆
        protected final function __clone(){}
    }
    
    $ins1 = Singleleton_4::getSingleleton(); //Fatal error: Uncaught Error: Call to protected Singleleton_4::__clone() from context
    $ins2 = clone $ins1;
    
    /**
     * 结论:可以将父克隆方法设置受保护final修饰,则实例不能被克隆
     */
    

    总结:单例模式原理是防止类被外部实例化,通过保护类的构造方法,并在类内部通过静态方式实例化来达到单例效果,一个完善单例模式应该满足一下几点

    • 类构造方法受保护,且final修饰,保证不能被外部实例化或子类覆写构造方法进行外部实例化
    • 类克隆方法受保护,且finals修饰,保证不能被克隆
  • 相关阅读:
    关于 setColorFilter 和 PorterDuff.Mode
    下拉刷新 SwipRefreshLayout
    from athletelist import AthleteList出现红色下滑波浪线警告
    IndentationError: unindent does not match any outer indentation level
    定制数据对象2
    定制数据对象
    数据处理02
    数据处理
    python 工具箱
    嵌套列表的格式打印
  • 原文地址:https://www.cnblogs.com/xiangdongsheng/p/13339889.html
Copyright © 2011-2022 走看看