设计模式笔记

1,设计模式主要分为3类:创建型、结构型、行为型

顾名思义,创建型模式,是为了创建对象使用的,至于为什么创建个对象(直接new一个不就完事了吗)还需要如此多不同的套路,后续你就知道,这边不赘述。结构性模式,是用来组织不同的小对象,从而变成更大更复杂结构的对象。行为型模式,是用来控制协调不同的对象的运行流程,因为实际开发场景下,不可能是孤零零一个对象在运行,会涉及多个对象交互,这中间的协调工作就会使用到行为型模式。

单例模式:

1,饿汉式:

package com.fsf;

public class HungrySingleton {
    //一个私有的构造方法
    private HungrySingleton(){//1

    }
    private static int flag = 1;
    //new一个private 以及static修饰的对象
    private static HungrySingleton hungrySingleton = new HungrySingleton();//2
    //写一个静态调用的方法
    public static HungrySingleton getHungrySingleton(){
        return hungrySingleton;
    }
  /**
   * 当外部调用HungrySingleton.getInstance()时,就会返回唯一的instance实例。为什么是唯一的?
   * 这代码中有几个要点
   * 标注1处该类的构造器用private修饰,防止外部手动通过new创建。后面的例子都需要这样,后面就不解释了。
   * 标注2处是核心,instance使用static修饰,然后调用new创建对象,我们知道static修饰的东西都属于类,
   * 而且在类加载阶段就已经被加载,并且只能被加载一次。就是类加载这种特性很好的保证了单例的特性,也天然防止了并发的问题。
   *
   *
   * 没错,一旦类初始化时就会创建这个对象,有人说,创建就创建呗,这有啥大不了的?大部分情况下确实是没啥问题,但是如果创建这个
   * 对象极其耗费时间和资源呢?这样必然会造成巨大的性能损耗。
   * 另外还有一种情况,有的时候我只是想单纯的加载一下类,但并不想去用该对象,那这个时候这种模式就属于浪费内存了。,
   * 如下代码,其他代码和上面一样,就是加了❶行,然后我现在外部调用HungrySingleton.flag,会发生什么?
   *
   * 会由于我只想调用一下上面flag,导致对象创建,然后内存泄露,有可能
   * */
}

2,懒汉式:

package com.fsf;
public class LazySingleton {
    private LazySingleton(){

    }
    private static volatile LazySingleton lazySingleton =null;//1

    public static synchronized LazySingleton getLazySingleton(){//2
        if(lazySingleton==null){//3

            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
    /**
     * 如果是多线程的情况,当两个线程同时到达3点那么将会创建两个对象 ,需要加同步锁
     *
     * 这代码中有几个要点
     * 标注1处其它和上面一样,多了一个volatile修饰,
     * 这主要是为了保证多线程下内存可见性。因为高速缓存关系,一个线程的修改并不一定要实时同步到另一线程,volatile可以用来解决这个问题。
     * 标注2处加synchronized同步锁,可以保证同一时刻只会有一个线程进入getInstance()方法,自然只会有一个线程调用instance = new LazySingleton(),
     * 单例自然就保证了。但同时这个带来了一个新问题,因为每个线程不管instance有没有被创建过,都会去调用getInstance(),
     * 因为if(instance == null)是需要进入方法后才判断的,然而getInstance()又是一个同步的,同一时刻只会有一个线程进入,
     * 其余线程都必须等待,这就会导致线程阻塞,导致性能下降。 ------------这块很6
     * */
}

3,比较完美的写法

package com.fsf;

public class PerfectSinleton {
    private PerfectSinleton(){}
    //恶汉的写法
    /**
     * 加volatile 的这个修饰符,保证了多线程的内存可见性,可以实现一个线程的修改实时同步到内存当中,别的线程得到的情况也是当前修改之后的情况
     *
     *
     * */
    private  static  volatile PerfectSinleton perfectSinleton=null;
    //该方法需要加同步锁,房子几个线程同时进来造成创建的不是单例的情况
    /**
     *为了不造成想成阻塞,需要做一个双重检查锁
     * */
    public static  PerfectSinleton getPerfectSinleton(){

        if(perfectSinleton==null){
            synchronized (PerfectSinleton.class){
                if(perfectSinleton==null){

                    perfectSinleton = new PerfectSinleton();
                }
            }
        }
        return perfectSinleton;

    }

}

4,最优写法,内部类的实现方法

package com.fsf;

import java.security.PrivateKey;

public class StaticInnerSingleton {
    private StaticInnerSingleton(){

    }
    /**
     * 1,静态内部类,外部类加载初始化的时候,并不会导致内部类StaticInnerSingletInstance的加载,实现了延迟加载
     */
    public static class StaticInnerSingletonInstance{
        private static final StaticInnerSingleton instance = new StaticInnerSingleton();
    }
    public static StaticInnerSingleton getInstance(){//2

        return StaticInnerSingletonInstance.instance;
    }
    /**
     * 当外部类调用2处的getInstance时,通过StaticInnerSingletonInstance.instance对instance的引用才会导致对象的创建,由于static的属性智慧根据
     * 类初始化加载一次,天然保证了线程安全的问题
     * */

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值