设计模式及单例设计模式
本章目标
-
掌握设计模式概念
-
重点掌握单例设计模式
设计模式概念
模式的起源
设计模式这一概念,起源于建筑领域,是由Christopher Alexander(克里斯托佛·亚历山大)及其团队,长时间通过对建筑行业的调查研究,总结了建筑行业可重复复用的解决方案,并记录在《建筑的永恒之道》中。
在书中,对模式的定义是:每个模式都描述了一个在环境中不断出现的问题,然后描述了该问题的解决方案核心,通过这种方式,可以无数次地重用那些已有的成功的解决方案,无须再重复相同的工作。
简单表述就是:模式是在特定环境下解决某类重复出现问题的一套成功或有效的解决方案。
从模式Pattern的定义中可以看到,每个模式是在特定的环境下才有效,学习模式,除了了解模式本身的,还得了解这个模式在什么环境下才能使用。
模式 = 套路
引入模式到软件工程
在1994年,四人组(Gang of Four),归纳并发表了 23 种在软件开发中使用频率较高的设计模式,把模式的概念引入软件工程中,即软件模式(Software Patterns)。当然,模式的概念不止存在于设计模式中,还包括了架构模式、分析模式、过程模式等,在软件周期的每个阶段,都有相应被总结的模式。
什么是设计模式
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使 用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可扩展性和可维护性。通用设计模式有23个,每一个设计模式都是某一类典型问题的解决方案。
设计模式的本质
设计模式的本质是面向对象编程技术的熟练和灵活运用,要真正理解设计模式就需要透彻理解面向对象设计原则和面向对象三大特性(封装、继承、多态)。
所有设计模式的书籍都是面向有一定 Java 语言基础和一定项目编程经验的读者
学习设计模式的误区
不要以为在任何一个系统中都要使用设计模式,系统也不是套用设计模式越多越好。滥用设计模式将增加系统复杂度,降低系统的可维护性。
学习设计模式五要素
-
名称:每一种设计模式都有名称,都是经过专门分类编目的,以便于学习交流
-
问题:每一种设计模式都是某一类典型问题的解决方案
-
实现:每一种设计模式都有一种或多种代码实现方式(UML类图)
-
优缺点:每一种设计模式都存在优缺点(没有完美无缺的解决方案)
-
适用场景:每一种设计模式都有其常见典型的适用场景
单例设计模式
定义
单例设计模式是 23 种设计模式中最简单、使用最频繁的设计模式,它为系统中的类只允许实例化唯一一个对象这类典型问题提供解决方案。
单例模式的实现方式有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
特点
1、单例类只能有实例化一个对象。 2、单例类必须自己创建自己的唯一实例化对象。 3、单例类必须给所有其他对象提供统一的对象引用方法。
单例实现方式
-
懒汉式
public class IdlerSingleton { private static IdlerSingleton singleton = null; private IdlerSingleton() { } public static synchronized IdlerSingleton getInstance() { // 线程同步 if ( null == singleton) { singleton = new IdlerSingleton(); } return singleton; } }
优点: 避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点: 懒汉式在单个线程中没有问题,但多个线程同事访问的时候就可能同事创建多个实例,而且这多个实例不是同一个对象,虽然后面创建的实例会覆盖先创建的实例,但是还是会存在拿到不同对象的情况。解决这个问题的办法就是加锁synchonized,第一次加载时不够快,多线程使用不必要的同步开销大。
-
饿汉式(推荐)
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
public class HungrySingleton { private static final HungrySingleton SINGLETON = new HungrySingleton(); private HungrySingleton() { } public HungrySingleton getInstance() { return SINGLETON; } }
优点
-
线程安全
-
在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点 资源效率不高,可能 getInstance() 永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化
-
静态内部类
class Test { private Test() { } private static class SingletonHelp { static Test instance = new Test(); } public static Test getInstance() { return SingletonHelp.instance; } }
优点:资源利用率高,不执行getInstance()不被实例,可以执行该类其他静态方法
缺点:第一次加载时反应不够快
总结