• 【设计模式】有些类也需要计划生育 单例模式


    一,概述

            单例模式确保某一个类只有一个实例,而且自行实例化(自己保存它的唯一实例)并向整个系统提供这个实例。这个类称为单例类。

            显然单例模式的要点有三个:

                                                             一是某个类只能有一个实例 (本身的初始方法为private,且只有实例为空的时候才建立)

                                                             二是它必须自行创建这个实例(作为一个成员方法,返回)

                                                             三是它必须自行向整个系统提供这个实例(返回的对象也是static)

    二,单例模式(C++)

             注意:

                     1)类方法要写到内部实现叫内联成员函数,在外部声明的叫外联函数。参考

                     2)在类内对象声明完成之后,要初始化赋值,由于类内部声明时候不能直接初始化,所以需要在外部初始化。

                     3)初始化方法是private,防止类外实例化。

                     4)GetInstance()方法是static

    #include <iostream>   
    using namespace std;   
    //单例类的C++实现   
    class Singleton   
    {   
    private:   
     	Singleton();//注意:构造方法私有   
     	virtual ~Singleton();   
     	static Singleton* instance;//惟一实例   
     	int var;//成员变量(用于测试)   
    public:   
     	static Singleton* GetInstance();//工厂方法(用来获得实例)   
     	int getVar();//获得var的值   
     	void setVar(int);//设置var的值   
    };   
    //构造方法实现   
    Singleton::Singleton()   
    {   
     this->var = 20;   
     cout<<"Singleton Constructor"<<endl;   
    } 
    
    Singleton::~Singleton()
    {
     if(instance != NULL)
     {
      delete instance;
     }
    }
    //初始化静态成员   
    //Singleton* Singleton::instance=new Singleton();  
    Singleton* Singleton::instance=NULL;//一定要初始化(由于不能在方法体内部初始化,所以就放到外部) 
    Singleton* Singleton::GetInstance()   
    {   
     if(instance == NULL)
     {
      instance = new Singleton();
     }
     return instance;   
    }   
     
    int Singleton::getVar()   
    {   
     	return this->var;   
    }   
    void Singleton::setVar(int var)   
    {   
     	this->var = var;   
    }   
    int main(int argc, char* argv[])   
    {   
     	Singleton *ton1 = Singleton::GetInstance();   
     	Singleton *ton2 = Singleton::GetInstance();   
     	cout<<"ton1 var = "<<ton1->getVar()<<endl;   
    	ton1->setVar(150);  
        cout<<"ton2 var = "<<ton2->getVar()<<endl;  
    	
    	 
     	return 0;   
    }  
    

    三,单例模式(JAVA)

    Danli.java   //没有main方法

    public class Danli {
    
        private static Danli instance = null; 
        private Danli()
        {
            
        }
        public static Danli getinstance()
        {
            if(instance == null)
            {
                instance = new Danli();
            }
            return instance; 
        }
       public void print()
       {
           System.out.println("这是通过单例模式调用");
       }
    }
    
    main.java  //使用单例模式类

    public class main {
        
         public static void main(String[] args)
        {  
             Danli d =Danli.getinstance();
             d.print();
             
            // Danli dd=new Danli();
             Danli dd=Danli.getinstance();
             
             if(d==dd)
                 System.out.println("两个实例相同");
             else
                 System.out.println("两个实例不同");
                 
        }
        
    }

    四,多线程时候的单例模式

            多线程的程序中,多个线程同时访问Singleton类,调用GetInstance()方法,会有可能造成创建多个实例。

            如何解决?

            加锁操作,确保当一个线程位于临界区时候,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待,直到该对象被释放。

            

    Singleton* Singleton::GetInstance()
    {
                if (instance == NULL) 
                {     
    			    lock(syncRoot)//实例未被创建时候加锁 
    				{
    					if(instance == NULL)
    					{
    						instance = new Singleton();
    					} 
    				}                                                                               
    				
                }
                return instance;
    }

     

    知识补充

           1,全局变量与全局静态变量的区别: 

                  (a) 若程序由一个源文件构成时,全局变量与全局静态变量没有区别。 

                  (b) 若程序由多个源文件构成时,全局变量与全局静态变量不同:全局静态变量使得该变量成为定义该变量的源文件独享,即:全局静态变量对组成该程序的其它源文件是无效的。 

                  (c) 具有外部链接的静态,可以在所有源文件里调用。除了本文件,其他文件可以通过extern的方式引用。

          2,静态全局变量的作用:

                  (a)  不必担心其它源文件使用相同变量名,彼此相互独立。

                  (b)  在某源文件中定义的静态全局变量不能被其他源文件使用或修改

                  (c)  只能在本文件中使用!具有内部链接的静态;不允许在其他文件里调用;


  • 相关阅读:
    面向对象C++编程与实践考试答案与解析
    退役记 Wallace
    ArcGIS中多来源栅格数据的像元对齐设置
    前端进行AES加密接口进行解密
    Java学习笔记 HashSet源码分析
    Java学习笔记 LinkedList源码分析
    Linux学习笔记1 安装JDK
    Java学习笔记 ArrayList源码分析
    Vue+Leaflet实现加载Stamen显示地图
    Leaflet中使用layerGroup图层组实现图层切换
  • 原文地址:https://www.cnblogs.com/secbook/p/2654977.html
Copyright © 2020-2023  润新知