栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

编程基础--以Java语言为基础的23种设计模式--创建者模式(Builder Pattern)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

编程基础--以Java语言为基础的23种设计模式--创建者模式(Builder Pattern)

      看本篇博客需要对JVM有一点点了解,当然可以在不懂的地方自己查也是可以的。另外如果有错误的地方,请评论区指正^^^

1、单例模式(Singleton Pattern)

        单例模式呢,顾名思义,在一个JVM运行实例中,某个类只有这么一个对象,无论在哪里获取该类的对象,得到的都是同一个对象,我们称这样的类的设计模式属于单例模式。

单例模式分类有两种:

        饿汉式:在类的加载(类的加载又分为主动使用和被动使用,一般被动使用不会触发clinit方法)时一般是在阶段该单例对象就会被创建。(饿汉给人的感觉就是上来就吃嘛…)

        懒汉式:顾名思义,听过懒加载的可能都知道懒的意思,就是用的时候再加载,放在这也就是第一次使用该单例对象的时候会被加载。

        1.1、饿汉式--(静态变量/静态代码块方式)--代码块里有评价
public class Test_01_StaticVar {
    //将构造器私有
    private Test_01_StaticVar(){}
    //定义一个私有的静态变量
    private static Test_01_StaticVar instance = new Test_01_StaticVar();
    //提供获取单例对象的静态方法
    public static Test_01_StaticVar getInstance(){
        return instance;
    }
}

或是这样子写,其实在字节码中都体现在方法中

public class Test_01_StaticVar {
    //将构造器私有
    private Test_01_StaticVar(){}
    //定义一个私有的静态变量
    private static Test_01_StaticVar instance = null;

    static {
       instance =  new Test_01_StaticVar();
    }
    public static Test_01_StaticVar getInstance(){
        return instance;
    }
}

//这种方式会在类加载时直接被创建,有关的评价说是因为可能被加载之后一直不使用造成内存浪费,
//很多人包括我也很纳闷,不主动使用怎么会导致类的加载。
        1.2、懒汉式--基础版本
public class Test_02_Lazy01 {
    private Test_02_Lazy01(){}
    private static Test_02_Lazy01 instance;
    public  static  Test_02_Lazy01 getInstance(){
        if(instance == null){
            instance = new Test_02_Lazy01();
        }
        return instance;
    }
}

//缺点就是在并发获取的情况下会造成不是单例的情况。
//例如但不限于以下一种情况:假设instance是null,当A线程指向到判断语句进入if开始new对象之前此线程的调度时间结束开始调度其他线程,
//另一个线程B在这段时间也执行了这个if语句并且也成功的进入if代码块内,之后就会导致两次创建这个对象。造成的结果就不符合单例这一条件。

一种解决方式如下:

public class Test_02_Lazy01 {
    private Test_02_Lazy01(){}
    private static Test_02_Lazy01 instance;
    public  static synchronized  Test_02_Lazy01 getInstance(){   <---不同点在这行
        if(instance == null){
            instance = new Test_02_Lazy01();
        }
        return instance;
    }
}

//synchronized写方法头上的缺点是性能不高,获取该对象就会获取锁。大多数是只需要读就可以的。只有第一次创建时获取锁才有意义
        1.3、懒汉式--升级版本--双重检查锁
public class Test_02_Lazy02 {
    private Test_02_Lazy02(){}
    private static Test_02_Lazy02 instance;
    
    public  static Test_02_Lazy02 getInstance(){
        if(instance == null){
            synchronized (Test_02_Lazy02.class) {
                if(instance == null)
                instance = new Test_02_Lazy02();
            }
        }
        return instance;
    }
}
//是不是感觉这样就很完美,其实不然
//还是有问题,可能会空指针异常,因为虚拟机优化的问题指令序列会重排(据说学过并发编程的应该知道。博主暂时没学)

睁大眼睛了,最终版本如下:
public class Test_02_Lazy02 {
    private Test_02_Lazy02(){}
    private static volatile Test_02_Lazy02 instance;
    
    public  static Test_02_Lazy02 getInstance(){
        if(instance == null){
            synchronized (Test_02_Lazy02.class) {
                if(instance == null)
                instance = new Test_02_Lazy02();
            }
        }
        return instance;
    }
}

volatile 关键字可以保证可见性和有序性。

        1.4、懒汉式--静态内部类方式

        静态内部类在主类加载的时候是不会被加载的,利用这个特点我们可以这样做:

public class Test_02_LazyInnerClass {
    private Test_02_LazyInnerClass(){}

    private static class TestHolder{
        private static final Test_02_LazyInnerClass INSTANCE = new Test_02_LazyInnerClass();
    }

    public  static Test_02_LazyInnerClass getInstance(){
        return TestHolder.INSTANCE;
    }
}
//这是比较推荐的方式,很多开源项目在用这种方式
enum Test_05_HangryEnum {
     INSTANCE;
     public void testmethod1(){
         System.out.println("我是实例方法一");
     }
    public void testmethod2(){
        System.out.println("我是实例方法二");
    }
    public Test_05_HangryEnum getInstance(){
         return INSTANCE;
    }
}
//有关枚举等价的类形式,请自行查阅

未完结。。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/310666.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号