前言
无论是在日常的工作中还是面试中,都必须会涉及到设计模式方面的知识,日常开发中,单例模式,代理模式等会经常使用。面试的时候也会被要求手写一些常用的设计模式。这里在此做个汇总:
《》
作用
- 提高代码维护性,可拓展性
- 提高代码复用率,降低开发成本
- 提高代码可读行,让代码容易让他人理解
设计原则
设计模式遵循以下原则:
- 1.单一职责原则
 一个类只有一种情况能引起它的变化,通俗的讲,一个类不要什么乱七八糟的东西都有,它的作用要简单纯粹。
- 2.开闭原则
 一个类一旦被引用,就尽量不要去修改原来的东西,可以通过添加拓展来实现想要的效果,更好的热插拔。
- 3.里氏替换原则
 是对开闭原则的补充,基类可以实现的行为,它的子类也可以实现。当子类替换掉基类时,既能复用父类,也能在子类上拓展新的行为。
- 4.依赖倒转原则
 是开闭原则的基础,日常开发中,要面向接口编程,面向抽象而不是面向具体。在使用具体的实现类时,尽量不与其他的具体实现类交互,而是与具体实现类的上层接口交互。这个在Java开发中十分常见。
- 5.接口隔离原则
 如果一个接口,实现类出现了没有具体实现该接口的方法,那么要把接口拆分出来写,反过来讲,即拆分出来的接口中的方法在实现类中要全部实现。
- 6.合成复用原则
 要尽量使用合成/聚合,尽量不要使用继承。
单例模式
一个简单的单例有以下3点要素
- 声明当前类的静态私有变量
- 构造方法私有化
- 公有方法返回唯一实例
- 简单懒汉式单例:1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16public class Singleton { 
 //1. 声明私有变量 ourInstance(用以记录 Singleton 的唯一实例)
 private static Singleton ourInstance = null;
 //2. 把类的构造方法私有化,不让外部调用构造方法实例化
 private Singleton() {
 }
 //3. 定义公有方法提供该类的全局唯一访问点
 //4. 外部通过调用getInstance()方法来返回唯一的实例
 public static Singleton newInstance() {
 if( ourInstance == null){//懒汉式
 ourInstance = new Singleton();
 }
 return ourInstance;
 }
 }
这样即可保证在进程中只有一个实例。
通常情况下单线程用上面的方法是没有问题的,但如果把它放进多线程的环境下,就会出现问题:多线程并发同时调用newInstance()方法,会重复创建实例。对此,需要进行加锁优化。
- 添加同步锁懒汉式单例: 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15class Singleton{ 
 private static Singleton instance = null;
 private Singleton(){}
 public static Singleton getInstance(){
 // 加入同步锁
 synchronized(Singleton.class) {
 if (instance == null)
 instance = new Singleton();
 }
 return instance;
 }
 }
添加了同步锁之后可以避免多线程并发引起的安全问题。
但是,同时加锁之后,每次访问都要进行线程同步,会耗时耗能。
综合上述问题,可采用静态内部类单例。
- 静态内部类懒汉式单例:
 在调用newInstance()方法时必须要先实例了Singleton,不能在newInstance中实例Singleton。利用静态内部类来完成调用前的加载。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18class Singleton { 
 
 // 1. 创建静态内部类
 private static class Singleton2 {
 // 在静态内部类里创建单例
 private static Singleton ourInstance = new Singleton();
 }
 // 私有构造函数
 private Singleton() {
 }
 
 // 延迟加载、按需创建
 public static Singleton newInstance() {
 return Singleton2.ourInstance;
 }
 }
- 外部调用类的newInstance()
- 自动调用Singleton2.ourInstance
- 此时单例类Singleton2得到初始化
- 而该类在装载 & 被初始化时,会初始化它的静态域,从而创建单例;
- 由于是静态域,因此只会JVM只会加载1遍,Java虚拟机保证了线程安全性
- 最终只创建1个单例
-饿汉式单例
唯一的区别是:
饿汉式:单例创建时机不可控,即类加载时,自动创建单例
懒汉式:单例创建时机可控,即有需要时,才手动创建单例
饿汉时单例是线程安全,能避免懒汉式因多线程引发的各种问题。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class Singleton {
    // 1. 加载该类时,单例就会自动被创建
    private static  Singleton ourInstance  = new  Singleton();
    
    // 2. 构造函数 设置为 私有权限
    // 原因:禁止他人创建实例 
    private Singleton() {
    }
    
    // 3. 通过调用静态方法获得创建的单例
    public static  Singleton newInstance() {
        return ourInstance;
    }
}
总结
主要介绍了设计模式的基本概念和单例模式,其他设计模式可参看:
设计模式(二):简单工厂与策略模式