您好,欢迎访问三七文档
PPT模板下载:单例模式主讲:张雷杰目的单例模式确保一个类仅有一个实例,且提供它的一个全局访问点原因有时我们只想让一个类的单个实例在系统中存在。我们需要让该实例易于被访问并且我们想要确保该类的其他实例不能被创建单例模式单例模式结构单例模式优点→对惟一实例的受控访问→允许可变的实例数量→能避免实例重复创建→应用于避免存在多个实例引起程序逻辑错误的场合→较节约内存单例模式的实现我们将使用静态方法来允许客户获得对单个实例的引用,并且将使用私有构造器!/***Singleton类是只允许一个实例化的类的实现*/publicclassSingleton{//Theprivatereferencetotheoneandonlyinstance.privatestaticSingletonuniqueInstance=null;//Aninstanceattribute.privateintdata=0;}单例模式的实现/***Returnsareferencetothesingleinstance.*Createstheinstanceifitdoesnotyetexist.*(Thisiscalledlazyinstantiation.)*/publicstaticSingletoninstance(){if(uniqueInstance==null)uniqueInstance=newSingleton();returnuniqueInstance;}单例模式的实现/***TheSingletonConstructor.*Notethatitisprivate!*NoclientcaninstantiateaSingletonobject!*/privateSingleton(){}//Accessorsandmutatorshere!}单例模式的实现以下是测试程序publicclassTestSingleton{publicstaticvoidmain(Stringargs[]){//GetareferencetothesingleinstanceofSingleton.Singletons=Singleton.instance();//Setthedatavalue.s.setData(34);System.out.println(Firstreference:+s);System.out.println(Singletondatavalueis:+s.getData());单例模式的实现//GetanotherreferencetotheSingleton.//Isitthesameobject?s=null;s=Singleton.instance();System.out.println(\nSecondreference:+s);System.out.println(Singletondatavalueis:+s.getData());}}outputsFirstreference:Singleton@1cc810Singletondatavalueis:34Firstreference:Singleton@1cc810Singletondatavalueis:34单例模式的实现注意:单例只在需要时才创建。这被称作被动实例化。如果两个线程同时调用instance()方法会怎么样?会产生什么问题?如何能预防这种情况哪?有几个方法:单例模式的实现单例模式的实现下面是具有主动实例化的单例模式。我们将在静态初始化器中创建Singleton实例。保证这种做法是线程安全的。/***Singleton类是只允许一个实例化的类的实现。*/publicclassSingleton{//Theprivatereferencetotheoneandonlyinstance.//Let’seagerlyinstantiateithere.privatestaticSingletonuniqueInstance=newSingleton();//Aninstanceattribute.privateintdata=0;单例模式的实现/***Returnsareferencetothesingleinstance.*/publicstaticSingletoninstance(){returnuniqueInstance;}/***TheSingletonConstructor.*Notethatitisprivate!*NoclientcaninstantiateaSingletonobject!*/privateSingleton(){}//Accessorsandmutatorshere!}主动实例化与被动实例化的区别主动实例化:在uniqueInstance被加载时就将自己实例化。为静态实例化方式。它在静态初始化期间或在类的构造器中分配变量。类一加载就实例化,所以要提前占用系统资源。被动实例化在第一次被引用时,才会将自己实例化。面临多线程访问的安全性问题,需要作双重锁定来保证安全。具有子类的Singleton如果想要能够生成Singleton的子类并让单个实例是子类的实例时该怎么办?例如,假定MazeFactory已生成子类EnchantedMazeFactory和AgentMazeFactory。我们只想实例化一个工厂,或者EnchantedMazeFactory或者是AgentMazeFactory。我们能怎样做哪?有几个方法:=由MazeFactory的静态instance()方法决定某个子类的实例来实例化。这项工作能通过参数或环境变量来完成。在这种情况下子类的构造器不能是私有的,因此客户端不能实例化子类的其他实例。=由每个子类提供一个静态的instance()方法。现在子类的构造器可以是私有的。具有子类的Singleton方法1方法1:由MazeFactory的instance()方法决定将实例化的子类/***MazeFactory类是只允许一个子类实例化的类的实现*/publicabstractclassMazeFactory{//Theprivatereferencetotheoneandonlyinstance.privatestaticMazeFactoryuniqueInstance=null;//TheMazeFactoryconstructor.//Ifyouhaveadefaultconstructor,itcannotbeprivate//here!protectedMazeFactory(){}具有子类的Singleton方法1//Returnareferencetothesingleinstance.//Ifinstancenotyetcreated,createenchantedasdefault.publicstaticMazeFactoryinstance(){if(uniqueInstance==null)returninstance(enchanted);elsereturnuniqueInstance;}//CreatetheinstanceusingthespecifiedStringname.具有子类的Singleton方法1publicstaticMazeFactoryinstance(Stringname){if(uniqueInstance==null)if(name.equals(enchanted))uniqueInstance=newEnchantedMazeFactory();elseif(name.equals(agent))uniqueInstance=newAgentMazeFactory();returnuniqueInstance;}}具有子类的Singleton方法1首先是创建工厂的客户代码:然后是访问工厂的客户代码:注意:EnchantedMazeFactory和AgentMazeFactory的构造器不能是私有的,因为MazeFactory必须能够实例化它们。因此,客户不可能实例化这些子类的其他实例。MazeFactoryfactory=MazeFactory.instance(enchanted);MazeFactoryfactory=MazeFactory.instance();具有子类的Singleton方法1(续)Theinstance(String)方法违反了开-闭原则,因为每个MazeFactory的新子类都必须修改它。publicstaticMazeFactoryinstance(Stringname){if(uniqueInstance==null)uniqueInstance=Class.forName(name).newInstance();returnuniqueInstance;}我们可以将Java类名作为instance(String)方法的参数来使用,以产生更简单的代码:具有子类的Singleton方法2方法2:由每个子类提供一个静态的instance()方法/***MazeFactory类是只允许一个子类实例化的类的实现*该版本要求其子类提供静态instance()方法的实现*/publicabstractclassMazeFactory{//Theprotectedreferencetotheoneandonlyinstance.protectedstaticMazeFactoryuniqueInstance=null;具有子类的Singleton方法2//TheMazeFactoryconstructor.//Ifyouhaveadefaultconstructor,itcannotbeprivate//here!protectedMazeFactory(){}//Returnareferencetothesingleinstance.publicstaticMazeFactoryinstance(){returnuniqueInstance;}}具有子类的Singleton方法2/***ClassEnchantedMazeFactoryisanimplementationofaclass*thatonlyallowsoneinstantiation.*/publicclassEnchantedMazeFactoryextendsMazeFactory{//Returnareferencetothesingleinstance.publicstaticMazeFactoryinstance(){if(uniqueInstance==null)uniqueInstance=newEnchantedMazeFactory();returnuniqueInstance;}//Privatesubclassconstructor!!privateEnchantedMazeFactory(){}具有子类的Singleton方法2首先是创建工厂的客户代码:然后是访问工厂的客户代码:注意:子类的构造器现在是私有的。只能创建子类的一个实例!MazeFactoryfactory=EnchantedMazeFactory.instance();MazeFactoryfactory=MazeFactory.instance();也要注意到如果在惟一的实例被创建前客户就调用MazeFactory.instance(),客户就能到一个null引用。最后,注意uniqueInstance现在是被保护的!单例模式是应用最广的模式之一,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,应用在一些创建对象需要消耗较多资源的地方。定义单例模式实现方式1.懒汉模式,2.DoubleCheckLock(DCL)实现单例,3.静态内部类,4.枚举单利,5.使用容器实现单例模式懒汉模式懒汉模式是申明一个
本文标题:单例模式-张雷杰
链接地址:https://www.777doc.com/doc-3626373 .html