项目中常用到的设计模式之单例模式详解

设计模式概览

1、创建型模式(Creational Patterns)

2、结构型模式(Structural Patterns)

3、行为型模式(Behavioral Patterns)

创建性模式:

        (1)工厂方法模式(Factory Method Pattern)

                (1.1)简单工厂模式(Simple Factory Pattern)

        (2)抽象工厂模式(Abstract Factory Pattern)

        (3)建造者模式(Builder Pattern)

        (4)原型模式(Prototype Pattern)

        (5)单例模式(Singleton Pattern)

结构型模式:

       (6)适配器模式(Adapter Pattern)

       (7)桥接模式(Bridge Pattern)

       (8)组合模式(Composite Pattern)

       (9)装饰者模式(Decorator Pattern)

      (10)外观模式(Facade Pattern)

      (11)享元模式(Flyweight Pattern)

      (12)代理模式(Proxy Pattern)

行为型模式:

      (13) 责任链模式(Chain of Responsibility Pattern)

      (14)命令模式(Command Pattern)

      (15)解释器模式(Interpreter Pattern)

      (16)迭代器模式(Iterator Pattern)

      (17)中介者模式(Mediator Pattern)

      (18)备忘录模式(Memento Pattern)

      (19)观察者模式(Observer Pattern)

      (20)状态模式(State Pattern)

      (21)策略模式(Strategy Pattern)

      (22)模板方法模式(Template Method Pattern)

      (23)访问者模式(Visitor Pattern)

设计模式(Design Pattern)是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。使用设计模式是为了可重用性代码,让代码更容易被他人理解,保证代码可靠性。

23中设计模式虽然每一种都有其独特的使用场景和作用,但在实际项目开发中常用到的还是其中几种,之后会依次介绍常用到的几种方式。本篇先从单例模式开始。

创建型模式之单例模式介绍

单例模式的优点:

1. 在内存中只有一个实例,减少了内存开销。

2. 可以避免对资源的多重占用。

3. 设置全局访问点,严格控制访问。

单例模式的缺点:

1. 没有接口,扩展困难。

2. 如果要扩展单例对象,只有修改代码,没有其他途径。

单例模式含义:

单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。

单例模式实现方式

1、饿汉式

随着类加载而初始化,并且创建单例对象

优点:

绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题。

没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好

缺点:

类加载的时候就初始化,不管用与不用都占着空间,浪费内存。

举例说明:

public class MkjHungrySingleton {
    /** 类的加载顺序:先静态、后动态、先属性、后方法。*/
    private static MkjHungrySingleton mkjHungrySingleton = new MkjHungrySingleton();
    /**私有构造器,防止其他类new */
    private MkjHungrySingleton(){}
    /**
     * 获取实例
     * @author: mkj
     * @return com.rhjt.mkjtest.singleton.MkjHungrySingleton
    */
    public static MkjHungrySingleton getInstance(){
        return mkjHungrySingleton;
    }
}
2、懒汉式

什么时候调用什么时候实例化,线程不安全

优点:

节省内存

缺点:

延时创建,需要时才创建实例效率慢,线程不安全。

下面我给出的例子是直接生产环境可以使用的

(1)双重锁检查模式
public class MkjIdlerSingleton {
    /**
     * 使用volatile防止指定重新排序
     */
    private static volatile MkjIdlerSingleton mkjIdlerSingleton = null;

    /**
     * 私有构造器,防止利用构造方法创建实例
     */
    private MkjIdlerSingleton() {
    }

    /**
     * 获取实例方法     * @return com.rhjt.mkjtest.singleton.MkjIdlerSingleton
     */
    public static MkjIdlerSingleton getInstance() {
        if (mkjIdlerSingleton == null) {
            synchronized (MkjIdlerSingleton.class) {
                if (mkjIdlerSingleton == null) {
                    mkjIdlerSingleton = new MkjIdlerSingleton();
                }
            }
        }
        return mkjIdlerSingleton;
    }
}
(2)静态内部类

这种形式兼顾饿汉式的内存浪费,也兼顾 synchronized 性能问题。内部类一定是要在方法调用之前初始化,巧妙地避免了线程安全问题。


public class MkjIdlerSingleton {
    /** 使用volatile防止指定重新排序*/
    private static volatile MkjIdlerSingleton mkjIdlerSingleton = null;
    /** 私有构造器,防止利用构造方法创建实例*/
    private MkjIdlerSingleton() {
    }
    /**
     * 获取实例方法
     * @return com.rhjt.mkjtest.singleton.MkjIdlerSingleton
    */
    public static MkjIdlerSingleton getInstance(){
        if (mkjIdlerSingleton==null){
            synchronized (MkjIdlerSingleton.class){
                if (mkjIdlerSingleton==null){
                    mkjIdlerSingleton = new MkjIdlerSingleton();
                }
            }
        }
        return mkjIdlerSingleton;
    }
}

注:使用饿汉式和懒汉式创建单例时避免使用反射和序列化创建对象,因为这两种方式会破坏单例结构。

3、枚举式单例

枚举式不会被反射和序列化破坏,对此具体原因感兴趣的同学可以去研究下源码。


public enum MkjEnumSingleton {
    INSTANCE;
    private String data;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    /** 获取实例*/
    public static MkjEnumSingleton getInstance() {
        return INSTANCE;
    }
}

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

missterzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值