设计模式学习系列——单例模式

Posted Andrés

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式学习系列——单例模式相关的知识,希望对你有一定的参考价值。

单例模式

  单例模式(Singleton Pattern),在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

  优点:1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如首页页面缓存)。 2)避免对资源的多重占用(比如写文件操作)。

  缺点:违背了“单一职责原则”,该类既是工厂又是产品(自己创建了自己);

  从具体实现角度来说,就是以下三点:

    一是单例模式的类只提供私有的构造函数,

    二是类定义中含有一个该类的静态私有对象,

    三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

  考虑以下场景,共享单车现在只有一辆,Jack和Mary都想使用。 这就用到了单例模式。

  使用内部静态类的方法创建,这种方法既保证了实例在第一次使用的时候创建,也保证了线程安全。参考php代码:

<?php
/*
 * 单例模式示例
 */
error_reporting(E_ALL);
ini_set(\'display_errors\',\'on\');
    

    //
    class SingletonBike{
        private static $instance = null; //创建静态私有的变量保存该类对象
        private $ownerUser = "";//使用者姓名
        
        //构造函数私有化,防止直接创建对象
        private function __construct($ownerUser) {
             $this ->ownerUser = $ownerUser;
        }
        //构造函数私有化,防止直接创建对象
      
       //防止克隆对象
        private function __clone() {
        }
        //静态方法,创建实例
        public static function getInstance($ownerUser){
            if(!self::$instance instanceof self){//self指类,this代表实例,这里指代静态属性,使用self
                self::$instance = new self($ownerUser);
                return self::$instance;
            }
            if(self::$instance->ownerUser == ""){
                self::$instance->ownerUser = $ownerUser;
                return self::$instance;
            }else{
                return null;
            }
        }
        public function getOwnerUser(){
            return $this->ownerUser;
        }
        //静态方法,销毁实例
        public static function destroyInstance(){
            //self::__destruct(); 
            self::$instance->ownerUser = "";
        }
    }

    
    $singletonBike = SingletonBike::getInstance("Mary");
    echo $singletonBike->getOwnerUser()."<br/>";//Mary
    $singletonBike2 = SingletonBike::getInstance("Jack");
    var_dump($singletonBike2);//null
    echo "<br/>";
    SingletonBike::destroyInstance();
    $singletonBike2 = SingletonBike::getInstance("Jack");
    var_dump($singletonBike2);//object(SingletonBike)#1 (1) { ["ownerUser":"SingletonBike":private]=> string(4) "Jack" }
    echo "<br/>";
    echo $singletonBike->getOwnerUser()."<br/>";//Jack
      
?>
View Code

Mary使用后,Jack不能使用。必须等到Mary不用以后,Jack才可以使用。

另一个版本,可以直接销毁单例创建的实例,节省内存,更优。如下:

<?php
/*
 * 单例模式示例
 */
error_reporting(E_ALL);
ini_set(\'display_errors\',\'on\');
    

    //
    class SingletonBike{
        private static $instance = null; //创建静态私有的变量保存该类对象
        private $ownerUser = "";//使用者姓名
        
        //构造函数私有化,防止直接创建对象
        private function __construct($ownerUser) {
             $this ->ownerUser = $ownerUser;
        }
        //构造函数私有化,防止直接创建对象
      
       //防止克隆对象
        private function __clone() {
        }
        //静态方法,创建实例
        public static function getInstance($ownerUser){
            if(!self::$instance instanceof self){//self指类,this代表实例,这里指代静态属性,使用self
                self::$instance = new self($ownerUser);
                return self::$instance;
            }else{
                return null;
            }
        }
        public function getOwnerUser(){
            return $this->ownerUser;
        }
        //静态方法,销毁实例
        public static function destroyInstance(&$instance){
            self::$instance = null;
            $instance = null;
        }
    }

    
    $singletonBike = SingletonBike::getInstance("Mary");
    echo $singletonBike->getOwnerUser()."<br/>";//Mary
    $singletonBike2 = SingletonBike::getInstance("Jack");
    var_dump($singletonBike2);//null
    echo "<br/>";
    SingletonBike::destroyInstance($singletonBike);
    $singletonBike2 = SingletonBike::getInstance("Jack");
    var_dump($singletonBike2);//object(SingletonBike)#1 (1) { ["ownerUser":"SingletonBike":private]=> string(4) "Jack" }
    echo "<br/>";
    var_dump($singletonBike);//为空
?>
View Code

js版本如下:

<!DOCTYPE html>
<html>
    <head>
        <title>单例模式示例</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script>
            var SingletonBikeController = (function(){//采用闭包来实现,因为有私有变量啊
                this.instance = null;
                
                this.SingleBike = function(ownerUser){
                    this.ownerUser = ownerUser;
                    this.getOwnerUser = function(){
                        return this.ownerUser;
                    }
                }
                return {//暴露的公共静态方法
                    "getInstance":function(ownerUser){
                        if(this.instance == null){
                            this.instance = new SingleBike(ownerUser);
                        }
                         return this.instance;
                    },
                    "destroyInstance":function(instance){
                        this.instance = null;
                        instance.ownerUser = "";
                    } 
                }
            })();
            
            var singletonBike = SingletonBikeController.getInstance("Mary");
            console.log(singletonBike.getOwnerUser());//mary
            singletonBike2 = SingletonBikeController.getInstance("Jack");
            console.log(singletonBike2.getOwnerUser());//mary
            SingletonBikeController.destroyInstance(singletonBike);
            console.log(singletonBike.getOwnerUser());//""
            singletonBike2 = SingletonBikeController.getInstance("Jack");
            console.log(singletonBike2.getOwnerUser());//jack
            
        </script>    
    </head>
</html>
View Code

 

参考文献:

单例模式

设计模式-——单例模式  

JS是按值传递还是按引用传递?

以上是关于设计模式学习系列——单例模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习系列——单例模式

第158天学习打卡(单例模式)

《C#零基础入门之百识百例》(四十五)类的属性 -- 单例模式

[js高手之路]设计模式系列课程-单例模式实现模态框

从源码中学习设计模式系列——单例模式序/反序列化以及反射攻击的问题

设计模式学习总结系列应用实例