学习设计模式最重要的是什么?我认为有一下四点,
一、明白该设计模式是为了解决何种问题而提出来的
二、设计模式的优缺点
三、何种场地才适合去使用他,做到规避利害
四、如何去实现一个设计模式(知道如何去书写)
这几天又回顾了一次设计模式中的单例模式,对其有了一个更深的理解,现在我们来谈谈单例模式
为什么需要单例模式?
我们初始学面向对象编程的时候,都是用new开始生成对象,哪里需要对象的时候直接一个new。即使几次传入构造函数的参数都是相同的,其实两个对象是不同的(当然重写equal()函数和hashcode()函数的那是例外),这样便会造成对象满天飞的情况,这样相当于栈里面的一个对象引用名都会指向一个堆里面的一个对象,这样导致堆里面出现过多重复的对象,会使性能下降。这时候,如果使用了单例模式,在相应类中声明一个静态类变量,初始值为null,如果该值不为null,则直接返回该变量,否则生成一个对象赋予静态变量。这样整个过程中,只需要生成一次对象。Spring容器中就有很明显的单例模式,比如Bean的作用域默认就是singleton,属于单例模式。总而言之,一个类从始至终只会生成一个实例,那就是单例模式
单例模式三要素
一、确保某一个类只有一个实例
二、不向外提供公有的构造函数,也可以理解为所有构造函数都是私有的,无法通过new的形式去获取该类的对象
三、自行实例化这一个实例并向外提供获取这个实例的公共方法
单例模式优缺点
单例模式的优点如下:
(1)、提供了唯一访问的受控访问,因为单例模式封装了它的唯一实例,所以它严格控制用户怎么以及何时去访问它
(2)、由于系统中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高性能
(3)、允许可变数目的实例,基于单例模式,开发人员可以对其自行扩展,使用与控制单例对象相似的方法来获得指定个数的实例对象,既节省资源,又解决了由于单例对象共享过多有损性能的可能(注:自行提供指定数目的实例对象的类可称之为多例类)
当然,单例模式的缺点也是很明显的,缺点如下:
(1)、由于单例模式没有抽象层。所以扩展很困难(一般设计成单例的类也不会想去扩展它吧)
(2)、职责多余沉重,他一定程度上是违反了单一职责原则,因为单例类不仅提供了业务方法,还提供了创建对象的方法(工厂方法),将创建对象与对象本身的功能耦合在了一起
(3)、现在很多面向对象的语言(JAVA、C#)的运行环境都提供了垃圾回收技术,因此,如果实例化的共享对象长时间不被利用,系统会认为它是一个垃圾,会自动销毁并回收资源,下次利用的时候又将重新实例化,这将导致共享的单例对象状态会丢失
单例模式使用的场景
一、系统只需要一个实例对象。例如:系统要求提供一个唯一的序列号生成器或者资源管理器,或者考虑到资源消耗太大而只允许创建一个对象
二、客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例
单例模式的三种经典实现(不论哪种实现都离不开单例模式的三要素)
(1)、懒汉模式(LazySingleton)
/** * 懒加载 。并不直接在初始化的时候实例化对象,而是在需要的时候在去加载对象,具有延迟效果,但是在 * 多个对象去同时加载时由于需要进行判断可能会出现多个对象 */ public class LazySingleton { private static LazySingleton instance =null; private LazySingleton(){} synchronized public static LazySingleton getInstance(){ if(instance==null){ instance=new LazySingleton(); } return instance; }
(2)、饿汉模式(EagerSingletion)
//不适用于多线程
public class EagerSingleton { //加载时就实例化对象 private static final EagerSingleton instance=new EagerSingleton(); //私有化构造函数 private EagerSingleton(){} //提供整个程序获取唯一实例的渠道 public static EagerSingleton getEagerSingleton(){ return instance; } }
(3)、IODH(Initialization On Demand Holder)内部类模式
//并不是所有面向对象语言都能够支持
public class InitializationOnDemandHolder { private InitializationOnDemandHolder(){} //在内部类中加载当前类的唯一实例 private static class HolderCLass{ private final static InitializationOnDemandHolder instance=new InitializationOnDemandHolder(); } public static InitializationOnDemandHolder getInstance(){ return HolderCLass.instance; } }
转载请注明出处,掌声送给社会人