Java学习之单例设计模式

news/2024/12/23 1:53:34/

目录

设计模式

单例模式

一、饿汉式

二、懒汉式

三、饿汉式VS懒汉式

总结


设计模式

1.静态方法和属性的经典使用

2.设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格以及解决问题的思考方式。就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考和摸索

单例模式

类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法

一、饿汉式

一般情况下创建对象的代码

package com.hspedu.single_;public class SingleTon01 {public static void main(String[] args) {GirlFriend gf1 = new GirlFriend("小红");GirlFriend gf2 = new GirlFriend("小黄");}
}
class GirlFriend {private String name;public GirlFriend(String name) {this.name = name;}
}

构造器私有化,构造器私有化之后无法在main方法内创建新对象 

private GirlFriend(String name) {
        this.name = name;
    }

 解决方法

1.构造器私有化

2.在类中创建新对象

3.创建public static 方法,在方法中return创建的新对象

4.在main方法中通过类名.方法名调用上述方法

package com.hspedu.single_;public class SingleTon01 {public static void main(String[] args) {
//        GirlFriend gf1 = new GirlFriend("小红");
//        GirlFriend gf2 = new GirlFriend("小黄");//调用静态方法,获取对象,接收返回的对象//调用静态方法,导致类加载,类加载只会进行一次GirlFriend gf1 = GirlFriend.getInstance();//输出对象,格式 全类名 + @ + 哈希值的十六进制System.out.println(gf1);System.out.println(gf1);}
}
//有一个类,GirlFriend
//只能有一个女朋友
class GirlFriend {private String name;//如何保障我们只能创建一个GirlFriend对象//单例模式-饿汉式//1.构造器私有化(防止new对象)//2.类的内部创建对象(static对象)//3.提供一个public static 方法,返回上述创建的对象//因为要在static方法中return,所以必须是static修饰private static final GirlFriend gf = new GirlFriend("小红");private GirlFriend(String name) {this.name = name;}//必须是static方法,因为构造器私有化,无法通过对象名.类名调用,只能通过类名.方法名调用public static GirlFriend getInstance(){return gf;}@Overridepublic String toString() {return "GirlFriend{" +"name='" + name + '\'' +'}';}
}

饿汉式的名称由来:在类加载的时候就已经创建好了对象,不论调用不调用,都已经创建好了

eg:

package com.hspedu.single_;public class SingleTon01 {public static void main(String[] args) {System.out.println(GirlFriend.n1);}
}
//有一个类,GirlFriend
//只能有一个女朋友
class GirlFriend {private String name;public static int n1 = 100;//如何保障我们只能创建一个GirlFriend对象//单例模式-饿汉式//1.构造器私有化(防止new对象)//2.类的内部创建对象(static对象)//3.提供一个public static 方法,返回上述创建的对象//因为要在static方法中return,所以必须是static修饰private static final GirlFriend gf = new GirlFriend("小红");private GirlFriend(String name) {System.out.println("构造器被调用");this.name = name;}//必须是static方法,因为构造器私有化,无法通过对象名.类名调用,只能通过类名.方法名调用public static GirlFriend getInstance(){return gf;}@Overridepublic String toString() {return "GirlFriend{" +"name='" + name + '\'' +'}';}
}

  

上述代码调用了静态变量n1,完成了类加载,所以对象gf也被创建了 

二、懒汉式

等用到的时候再创建对象

package com.hspedu.single_;public class SingleTon02 {public static void main(String[] args) {//调用静态方法,cat的默认值为null//执行 cat = new Cat("圆圆");Cat instance = Cat.getInstance();System.out.println(instance);//再次调用静态方法getInstance()//经过上述操作,对象cat 已经 ≠ null//不会再创建新对象,还是输出“圆圆”Cat instance1 = Cat.getInstance();System.out.println(instance1);}
}
class Cat{private String name;private static Cat cat;//对象为引用//构造器私有化//定义一个静态属性:对象//提供一个public static 方法,返回对象private Cat(String name) {System.out.println("构造器被调用");this.name = name;}public static Cat getInstance(){if(cat == null){cat = new Cat("圆圆");}return cat;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';}
}

只有一个对象实例,第二次调用的时候输出的还是第一次创建的对象实例,因此,构造器也只会调用一次

三、饿汉式VS懒汉式

二者最主要的区别在于

1.创建对象的时机不同: 饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建

2.饿汉式不存在线程安全问题,懒汉式存在线程安全问题。(线程还没学到)

3.饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。


4.在我们javaSE标准类中,java.lang.Runtime就是经典的单例模式

代码

public class Runtime {//私有的static属性:变量;在类加载的时候就会创建,饿汉式private static final Runtime currentRuntime = new Runtime();private static Version version;//public static 方法 返回currentRuntimepublic static Runtime getRuntime() {return currentRuntime;}//构造器私有化private Runtime() {}
}

总结

1.单例模式的两种实现方式(1) 饿汉式(2) 懒汉式

2.饿汉式的问题:在类加载时候就创建,可能存在资源浪费问题

3.懒汉式的问题: 线程安全问题,后面学了线程后,再进行完善


http://www.ppmy.cn/news/11715.html

相关文章

【Nginx】Nginx配置实例-反向代理

1. 反向代理实例一 实现过程 1. 启动一个 tomcat,浏览器地址栏输入 127.0.0.1:8080,出现如下界面2. 通过修改本地 host 文件,将 www.123.com 映射到 127.0.0.13. 在 nginx.conf 配置文件中增加如下配置 2. 反向代理实例二 实现过程 1.准备两…

机器学习--方差和偏差、Bagging、Boosting、Stacking

目录 一、方差和偏差 数学定义 对公式的解释 减小偏差、方差、噪声 总结 二、Bagging 代码实现 bagging什么时候会变好 不稳定的learner ​总结 三、Boosting Gradient boosting gradient boosting 的代码实现 gradient boosting的效果 ​总结 四、Stacking st…

PyQt5 serial模块-串口小工具

PyQt5 serial模块-串口小工具串口简述serial模块参数方法使用模板串口工具示例串口简述 异步串行是指UART(Universal Asynchronous Receiver/Transmitter),通用异步接收/发送。UART是一个并行输入成为串行输出的芯片,通常集成在主…

React 学习笔记总结(七)

针对React拓展相关的学习。 文章目录一. React 项目打包二. React扩展 之 setState两种写法三. React扩展 之 lazyLoad(懒加载)四、React的 stateHook五、React 的 Effect Hook六、React 的 RefHook七、React 的 Fragment八、React 的 Context九、React 的 PureComponent1. Com…

windows排查问题常用命令

查看JAVA进程占用PID: wmic process where caption"java.exe" get processid,caption,commandline /value查看进程端口信息:netstat -ano 或者 netstat -ano|findstr "8080" 或查看成功建立连接的:netstat -ano | findstr “ESTABLI…

本地小说阅读网站打造

目录 一、本地小说网站总体组织框架 1、所需的VUE库和elementLib以及JQ库 2、本地目录设计 3、整体代码样式 二、正文核心代码 1、引入element 样式,和自定义的样式 2、引入JS 3、自定义Header组件 1)vue 定义MyHeader组件 2)MyHead…

Vue项目大概目录介绍

后端,自己学习做个记录.实话是看不懂全靠抄. 这是一个刚建好的Vue项目 node_modules:整个项目用到的依赖文件 public--->favicon.ico:Vue的图标 public--->index.html:可以理解为首页入口,模板页,开发的时候用不到,Vue是个单页面应用,开发也用不到 src:好比项目的源码…

【Linux】编译器 - gcc 函数库

目录 一、背景知识 二、gcc如何执行 1、预处理 2、编译 3、汇编 4、链接 三、函数库 1、初识函数库 2、动静态库 2.1、动态库 2.2、静态库 2.3、动静态库的选择 一、背景知识 使用 vim 编辑器完成代码书写之后,我们需要使用 Linux 中的编译器 gcc 来对…