iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java单例模式怎么理解
  • 433
分享到

Java单例模式怎么理解

2023-06-22 08:06:28 433人浏览 薄情痞子
摘要

这篇文章主要讲解了“Java单例模式怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java单例模式怎么理解”吧!一、设计模式概览1.1、软件设计模式的概念软件设计模式(Softwar

这篇文章主要讲解了“Java单例模式怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java单例模式怎么理解”吧!

一、设计模式概览

1.1、软件设计模式的概念

软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。

1.2、软件设计模式的基本要素

1. 模式名称

 每一个模式都有自己的名字,通常用一两个词来描述,可以根据模式的问题、特点、解决方案、功能和效果来命名。模式名称(PatternName)有助于我们理解和记忆该模式,也方便我们来讨论自己的设计。

2. 问题

问题(Problem)描述了该模式的应用环境,即何时使用该模式。它解释了设计问题和问题存在的前因后果,以及必须满足的一系列先决条件。

3. 解决方案

模式问题的解决方案(Solution)包括设计的组成成分、它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象的 组合)来解决这个问题。

4. 效果

描述了模式的应用效果以及使用该模式应该权衡的问题,即模式的优缺点。主要是对时间和空间的衡量,以及该模式对系统的灵活性、扩充性、可移植性的影响,也考虑其实现问题。显式地列出这些效果(Consequence)对理解和评价这些模式有很大的帮助。

1.3、GoF 的 23 种设计模式的分类和功能

1. 根据目的来分

根据模式是用来完成什么工作来划分,

创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。

结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。

行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

2. GoF的23种设计模式的功能

单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。

抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。

建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。

外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。

享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。

组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。

模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。

命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。

职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。

观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。

备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。

解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

1.4、软件设计的七大原则

软件设计的七大原则
原则描述作用
开闭原则对扩展开放,对修改关闭降低维护带来的新风险
依赖倒置原则高层不应该依赖低层,要面向接口编程更利于代码结构的升级扩展
单一职责原则一个类只干一件事,实现类要单一便于理解,提高代码的可读性
接口隔离原则一个接口只干一件事,接口要精简单一功能解耦,高聚合、低耦合
迪米特法则不该知道的不要知道,一个类应该保持对其它对象最少的了解,降低耦合度只和朋友交流,不和陌生人说话,减少代码臃肿
里氏替换原则不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义防止继承泛滥
合成复用原则尽量使用组合或者聚合关系实现代码复用,少使用继承降低代码耦合

实际上,这些原则的目的只有一个:降低对象之间的耦合,增加程序的可复用性、可扩展性和可维护性。

记忆口诀:访问加限制,函数要节俭,依赖不允许,动态加接口,父类要抽象,扩展不更改。

在程序设计时,我们应该将程序功能最小化,每个类只干一件事。若有类似功能基础之上添加新功能,则要合理使用继承。对于多方法的调用,要会运用接口,同时合理设置接口功能与数量。最后类与类之间做到低耦合高内聚。

 二、单利模式

1.1、单例模式的相关定义

        指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

单利模式三个特点

单例类只有一个实例对象;

该单例对象必须由单例类自行创建;

单例类对外提供一个访问该单例的全局访问点。  

单例模式的优点

单例模式可以保证内存里只有一个实例,减少了内存的开销。

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

单例模式设置全局访问点,可以优化和共享资源的访问。

单例模式的缺点:

单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。

并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。

单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。

单例模式的应用场景

需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC

某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。

某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。

某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程线程池网络连接池等。

频繁访问数据库或文件的对象。

对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,如果有多个实例,则系统会完全乱套。

当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 WEB 中的配置对象、数据库的连接池等。

1.2、单利模式的结构

单例类:包含一个实例且能自行创建这个实例的类。

访问类:使用单例的类。

2.1单利模式的实现方式一:懒汉式

该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。

代码:

public class LazySingleton {         //构造器私有,堵死了外界利用new创建此类对象的可能        private LazySingleton(){                System.out.println("yese");         }        //提供对象,是外界获取本类对象的唯一全局访问点        private static LazySingleton lazySingleton;         public static  LazySingleton getInstance(){                //如果对象不存在,就new一个新的对象,否则返回已有的对象                if(lazySingleton == null) {                        lazySingleton = new LazySingleton();                }                return lazySingleton;        }}
 @Test    public void testLazy() {        LazySingleton l1 = LazySingleton.getInstance();        LazySingleton l2 = LazySingleton.getInstance();        System.out.println(l1+"\n" + l2);        System.out.println(l1 == l2);    }

测试结果:  

com.singletonPattern.LazySingleton@78e03bb5
com.singletonPattern.LazySingleton@78e03bb5
true

 该代码很显然是不适合多线程模式的,这时候就需要给单例模式的对象加上一把

class LazySingleton2{        //构造器私有,堵死了外界利用new创建此类对象的可能        private LazySingleton2(){                System.out.println("s2");         }        //提供对象,是外界获取本类对象的唯一全局访问点        private static LazySingleton2 lazySingleton2;         public static  LazySingleton2 getInstance(){                //如果对象不存在,就new一个新的对象,否则返回已有的对象                if(lazySingleton2 == null) {                        synchronized(LazySingleton2.class) {                                if(lazySingleton2 == null) {                                        lazySingleton2 = new LazySingleton2();                                }                        }                }                return lazySingleton2;        }}

这时还有一个问题,就是在创建一个对象时,在JVM中会经过三步:

(1)为对象分配内存空间

(2)初始化该对象

(3)将该对象指向分配好的内存空间

 那么在执行我们这个多线程代码的过程中,有可能他不按照这三部的顺序走,那么就会导致一个指令重排的问题,解决此问题的方法就是加关键字volatile

class LazySingleton3{        //构造器私有,堵死了外界利用new创建此类对象的可能        private LazySingleton3(){        }        //提供对象,是外界获取本类对象的唯一全局访问点        private volatile static LazySingleton3 lazySingleton3;         public static  LazySingleton3 getInstance(){                //如果对象不存在,就new一个新的对象,否则返回已有的对象                if(lazySingleton3 == null) {                        synchronized(LazySingleton3.class) {                                if(lazySingleton3 == null) {                                        lazySingleton3 = new LazySingleton3();                                }                        }                }                return lazySingleton3;        }}

最后我们还可以去解决一下反射来破坏单利模式

class LazySingleton4 {    //提供变量,控制反射    public static boolean s = false;     //构造器私有,堵死了外界利用new创建此类对象的可能    private LazySingleton4() {        if (s == false) {            //当第一个对象成功获取之后,第二个对象就不能通过反射获取了            s = true;        } else {            throw new RuntimeException("不要用反射破坏异常");        }     }     //提供对象,是外界获取本类对象的唯一全局访问点    private volatile static LazySingleton4 lazySingleton4;     public static LazySingleton4 getInstance() {        //如果对象不存在,就new一个新的对象,否则返回已有的对象        if (lazySingleton4 == null) {            synchronized (LazySingleton4.class) {                if (lazySingleton4 == null) {                    lazySingleton4 = new LazySingleton4();                }            }        }        return lazySingleton4;    }}

volatile, synchronized这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。

2.2单利模式的实现方式一:饿汉式

该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。

代码:

public class HungrySingleton {    private static final HungrySingleton instance = new HungrySingleton();    private HungrySingleton() {    }    public static HungrySingleton getInstance() {        return instance;    }}

饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。

感谢各位的阅读,以上就是“Java单例模式怎么理解”的内容了,经过本文的学习后,相信大家对Java单例模式怎么理解这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: Java单例模式怎么理解

本文链接: https://www.lsjlt.com/news/303576.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java单例模式怎么理解
    这篇文章主要讲解了“Java单例模式怎么理解”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java单例模式怎么理解”吧!一、设计模式概览1.1、软件设计模式的概念软件设计模式(Softwar...
    99+
    2023-06-22
  • 如何理解Java单例模式
    本篇内容介绍了“如何理解Java单例模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 一、介绍...
    99+
    2024-04-02
  • Java单例模式怎么写
    本篇内容主要讲解“Java单例模式怎么写”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java单例模式怎么写”吧!这个模式是很有意思,而且比较简单,但是我还是要说因为它使用的是如此的广泛,如此的...
    99+
    2023-06-19
  • 如何理解Java设计模式的单例模式
    这篇文章主要讲解了“如何理解Java设计模式的单例模式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解Java设计模式的单例模式”吧!一、什么是单例模式单例模式是一种常用的软件设计模式...
    99+
    2023-06-25
  • 深入理解Java设计模式之单例模式
    目录一、什么是单例模式二、单例模式的应用场景三、单例模式的优缺点四、单例模式的实现1.饿汉式2.懒汉式3.双重加锁机制4.静态初始化五、总结一、什么是单例模式 单例模式是一种常用的软...
    99+
    2024-04-02
  • Java 实例解析单例模式
    目录单例模式的介绍优点缺点SynchronizedSynchronized示例Synchronized与非SynchronizedSingleton第一个示例第二个示例第三个示例第四...
    99+
    2024-04-02
  • Java单例模式与破坏单例模式概念原理深入讲解
    目录什么是单例模式饿汉式(预加载)懒汉式(懒加载)反射破坏单例模式什么是单例模式 经典设计模式又分23种,也就是GoF 23 总体分为三大类: 创建型模式结构性模式行为型模式 Jav...
    99+
    2023-02-21
    Java单例模式 Java破坏单例模式
  • Java单例模式的攻击与防御怎么理解
    这篇文章主要介绍“Java单例模式的攻击与防御怎么理解”,在日常操作中,相信很多人在Java单例模式的攻击与防御怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java单例模式的攻击与防御怎么理解”的疑...
    99+
    2023-06-02
  • java中单例模式讲解
    目录WHATWHYHOW饿汉式实现一:静态实例参数与静态代码块实现二:静态内部类懒汉式错误一:单线程实现错误二:同步方法错误三:同步代码块之单次检查错误四:同步代码块之双重检查正确:...
    99+
    2024-04-02
  • java单例模式怎么实现
    Java中单例模式的实现方法有以下几种:1. 懒汉式(线程不安全):```public class Singleton {priva...
    99+
    2023-08-23
    java
  • Java中单例模式怎么用
    这篇文章给大家分享的是有关Java中单例模式怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。注意单例类只能有一个实例。单例类必须自己创建自己的唯一实例。单例类必须给所有其他对象提供这一实例。优点在内存里只有一...
    99+
    2023-06-29
  • Java设计模式之单例模式示例详解
    目录0.概述1.饿汉式1.1 饿汉式单例实现1.2 破坏单例的几种情况1.3 预防单例的破坏2.枚举饿汉式2.1 枚举单例实现2.2 破坏单例3.懒汉式4.双检锁懒汉式5.内部类懒汉...
    99+
    2024-04-02
  • java 单例模式和工厂模式实例详解
    单例模式根据实例化对象时机的不同分为两种:一种是饿汉式单例,一种是懒汉式单例。私有的构造方法指向自己实例的私有静态引用以自己实例为返回值的静态的公有的方法饿汉式单例 public class Singleton { private ...
    99+
    2023-05-31
    java 单例模式 工厂模式
  • JAVA设计模式之单例模式详解
    目录前言一、单例模式是什么?二、懒汉式单例三、饿汉式单例四、双重校验锁总结前言 在之前的文章里已经介绍了设计模式以及设计原则的概念,接下来我们从单例模式入手深入学习几种常用的JAVA...
    99+
    2024-04-02
  • java设计模式之单例模式解析
    单例模式是最简单但同时也是很重要的一种设计模式,优点有以下几个方面:当内存占用特别大的类需要频繁地创建销毁时,单例模式可以节省内存和提高性能,例如myBatis里面的sessionFactory当需要对文件做单一读写时,例如同一时间只能同时...
    99+
    2023-05-31
    java 设计模式 单例模式
  • java 单例模式的实例详解
    java 单例模式的实例详解概念:    java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。    单例模式有一下特点:   1、单例类只能有一个实例。   2、单例类必须自己自己创建自己的唯一...
    99+
    2023-05-31
    java 单例模式 ava
  • Java设计模式-单例模式
    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供...
    99+
    2023-06-05
  • java的单例模式怎么实现
    今天小编给大家分享一下java的单例模式怎么实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下...
    99+
    2024-04-02
  • 怎么掌握Java的单例模式
    这篇“怎么掌握Java的单例模式”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么掌握Java的单例模式”文章吧。单例模式:...
    99+
    2023-06-30
  • Java 单例模式详细解释
    目录饿汉式懒汉式懒汉式(加锁synchronized)懒汉式(部分加锁synchronized)懒汉式(DCL)懒汉式(DCL)最终版静态内部类总结饿汉式 public cla...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作