浅谈设计模式及Singleton

前言

在我们平时的工作学习中,代码的整洁与高可用会让程序更加有效率,对项目的好处不言而喻。

设计模式的学习会让我们的编程水平得到很大的提升,同时也有助于对框架的理解,因为优秀的框架结构都用到了设计模式。

今天先瞅瞅单例模式,剩余的设计模式我也会慢慢更新,做一个系列。


设计模式(design pattern)?

设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 是对面向对象设计中反复出现的问题的解决方案

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

Java设计模式贯彻的原理是:面向接口编程,而不是面向实现。其目标的原则是:降低耦合,增强灵活性。

设计模式分类:

一、创建型模式

创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其关联对象的创建、组合和表示方式。

所有的创建型模式都有两个主要功能:

  1. 将系统所使用的具体类信息封装起来;
  2. 隐藏类的实例是如何被创建和组织的。外界对于这些对象只知道他们共同的接口,而不清楚其具体的实现细节。

常见的创建型模式:

  • 单例模式(Singleton Pattern)
  • 工厂方法模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 建造者模式(Builder Pattern)
  • 原型模式(Prototype pattern)

二 、结构型模式

结构型模式讨论的是类和对象的结构,它采用继承机制来组合接口或实现(类结构型模式),或者通过组合一些对象实现新的功能(对象结构型模式)。

常见结构型模式:

  • 代理模式(Proxy)
  • 装饰模式(Decorator)
  • 适配器模式(Adapter)
  • 组合模式(Composite)
  • 桥梁模式(Bridge)
  • 外观模式(Facade)
  • 享元模式(Flyweight)

三、行为型模式

行为型模式关注的是对象的行为,用来解决对象之间的联系问题。

常见行为型模式:

  • 模板方法模式(Template Method)
  • 命令模式(Commend)
  • 责任链模式(Chain of Responsibility)
  • 策略模式(Strategy)
  • 迭代器模式(Iterator)
  • 中介者模式(Mediator)
  • 观察者模式(Observer)
  • 备忘录模式(Memento)
  • 访问者模式(Visitor)
  • 状态模式(State)
  • 解释器模式(Interpreter)

Singleton Pattern(单例模式)?

定义:Ensure a class has only one instance, and provide a global Point of access to it.
确保一个类只有一个实例存在。

最好学习方法就是分析代码:

饿汉式

/**
 * 饿汉式(类加载时,就进行对象实例化)
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 类只加载一次,实例化一次   Class.forName()
 * 缺点:类完成加载,就完成实例化
 */
public class Manager01 {
	//private确保构造方法无法被外界实例化
    private Manager01(){
    }
    //静态常量(或变量)
    private static final Manager01 INSTANCE = new Manager01();
	//通过该方法获得实例
    public static Manager01 getInstance(){
        return INSTANCE;
    }
	//其余业务方法
    public void useOthers(){
    }

    public static void main(String[] args) {
    	
        Manager01 instance1 = Manager01.getInstance();
        Manager01 instance2 = Manager01.getInstance();
		//输出结果为True,同一个对象
        System.out.println(instance1==instance2);
    }
}

懒汉式

/**
 * 懒汉式(第一次引用类时,才进行对象实例化)
 * Lazy Loading
 * 按需初始化,但要保证多线程并发安全
 */
public class Manager02 {
    private Manager02(){}
    private static Manager02 INSTANCE;

    public static Manager02 getInstance(){
    //public static synchronized Manager02 getInstance()
    //加锁亦可在方法上,保证同步,多线程容易发生创建多个实例
        synchronized (Manager02.class){
        	//判断是否已实例化
            if (INSTANCE==null){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                INSTANCE = new Manager02();
            }
            return INSTANCE;
        }
    }
	//业务方法等
    public void useOthers(){}

    public static void main(String[] args) {
    	//创建100个线程,结果只有一个实例被创建
        for (int i = 0; i < 100; i++) {
            //lambda表达式
            new Thread(()->{
                System.out.println(Manager02.getInstance().hashCode());
            }).start();
        }
    }
}

双重判断

懒汉式模式会加锁,导致效率降低,双重模式是对懒汉的优化

/**
 * 双重判断
 */
public class Manager03 {
    private Manager03(){}
    private static Manager03 instance;

    public static Manager03 getInstance(){
        
        //判断第一次,若实例已存在,直接跳转返回instance。无需等待锁的释放
       if (instance==null){
           synchronized (Manager03.class){
           	    //二次判断,若此时已存在实例,就跳过if块
               if (instance==null){
                   try {
                       Thread.sleep(10);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   
                   instance = new Manager03();
                   return instance;
               }
           }
       }
       return instance;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Manager03.getInstance().hashCode());
            }).start();
        }
    }
}

静态内部类

/**
 * 静态内部类
 * 加载外部类时不会加载内部类,懒加载
 */
public class Manager04 {
    private Manager04(){}

    private static class managerHolder { 
        private final static Manager04 INSTANCE = new Manager04();
    }

    public static Manager04 getInstance(){
        return managerHolder.INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Manager04.getInstance().hashCode());
            }).start();
        }
    }
}

枚举式

/**
 * 枚举单例
 * 大佬写的,不仅解决线程同步,还可以反序列化
 * 完美
 */
public enum Manager05 {

    INSTANCE;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(Manager05.INSTANCE.hashCode());
            }).start();
        }
    }
}

最常用最简单的就是饿汉式,懒汉式了。

上面示例为看视频总结手敲,很精妙

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值