Java学习——设计模式——创建型模式1

文章目录

  • 创建型模式
    • 单例
      • 饿汉式
      • 懒汉式
      • 存在的问题
    • 工厂方法
      • 简单工厂模式
      • 工厂方法模式
      • 抽象工厂模式

创建型模式

关注点是如何创建对象,核心思想是要把对象创建和使用相分离,这样两者能相对独立地变换

包括:
1、工厂方法:Factory Method
2、抽象工厂:Abstarct Factory
3、建造者:Builder
4、原型:Prototype
5、单例:Singleton

单例

最简单的设计模式之一,目的是为了保证在一个进程中,某个类有且仅有一个实例。

结构
单例模式主要有以下角色:

  • 单例类。只能创建一个实例的类。
  • 访问类。使用单例类。

分类

  • 饿汉式:类加载就会导致单实例对象被创建
  • 懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

饿汉式

1、静态变量方式

/*
    饿汉式
        静态变量创建类的对象
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    成员位置创建该类的对象
    private static Singleton instance = new Singleton();

//    对外提供静态方法获取该对象
    public static Singleton getInstance(){
        return instance;
    }
}

instance对象是随着类的加载而创建的。如果该对象足够大的话,而一直没有使用就会造成内存浪费。

2、静态代码块方式

package DesignPattern.Single.demo2;

/*
    饿汉式
        静态代码块中创建类的对象
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    成员位置创建该类的对象
    private static Singleton instance;
    
    static {
        instance = new Singleton();
    }

//    对外提供静态方法获取该对象
    public static Singleton getInstance(){
        return instance;
    }
}

也存在内存浪费问题

3、枚举方式

枚举类实现单例模式是激励推荐的单例实现模式,因为枚举类型是线程安全的,并且只会装载一次,设计者充分的利用了枚举的这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是所用单例实现中唯一一种不会被破坏的单例实现模式。

public enum Singleton{
	INSTANCE;
}

懒汉式

1、线程不安全

/*
    懒汉式
        线程不安全
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    声明Singleton类型的变量instance
    private static Singleton instance;

//    对外提供访问方式
    public static Singleton getInstance(){
//        判断instance是否为null,如果为null,说明还没有创建Singleton的对象
        if(instance == null){
        //如果有两个线程,线程1等待,线程2获取到CPU的执行权,也会进入到该判断
            instance=new Singleton();
        }
        return instance;
    }
}

2、线程安全

/*
    懒汉式
        线程安全
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    声明Singleton类型的变量instance
    private static Singleton instance;

//    对外提供访问方式
    public static synchronized Singleton getInstance(){
//        判断instance是否为null,如果为null,说明还没有创建Singleton的对象
        if(instance == null){
            instance=new Singleton();
        }
        return instance;
    }
}

3、双重检查锁

/*
    懒汉式
        双重检查锁
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    声明Singleton类型的变量instance
    private static Singleton instance;

//    对外提供访问方式
    public static Singleton getInstance(){
//        第一次判断,如果instance的值不为null,不需要抢占锁,直接返回对象
        if(instance == null){
            synchronized (Singleton.class){
//              第二次判断
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

双重检查锁模式解决了单例、性能、线程安全问题,但在多线程的情况下,可能会出现空指针问题,出现问题的原因是JVM在实例化对象的时候会进行优化和指令重排序操作。

要解决双重检查锁模式带来空指针异常的问题,只需要使用volatile关键字,volatile关键字可以保证可见性和有序性

/*
    懒汉式
        双重检查方式
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//    声明Singleton类型的变量instance
    private static volatile Singleton instance;

//    对外提供访问方式
    public static Singleton getInstance(){
//        第一次判断,如果instance的值不为null,不需要抢占锁,直接返回对象
        if(instance == null){
            synchronized (Singleton.class){
//              第二次判断
                if(instance==null){
                    instance=new Singleton();
                }
            }
        }
        return instance;
    }
}

4、静态内部类方式
JVM在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性。静态属性由于被static修饰,保证只被实例化一次,并且严格保证实例化顺序

/*
    懒汉式
        静态内部类方式
 */

public class Singleton {
//    私有构造方法
    private Singleton() {}

//  定义一个静态内部类
    private static class SingletonHolder{
//        在内部类中声明并初始化外部类的对象
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance(){
        return SingletonHolder.INSTANCE;
    }

}

存在的问题

单例有可能被破坏,序列化和反射可以在单例中创建多个对象,枚举除外。

工厂方法

简单工厂模式

不是23种设计模式,比较像一种编程习惯

结构
1、抽象产品
2、具体产品
3、具体工厂

原来:
CoffeeStore–匹配咖啡种类
Coffee
AmericanCoffee
LatteCoffee

简单工厂:
CoffeeStore–调用工厂类
SimpleCoffeeFactory–匹配咖啡种类

public class SimpleCoffeeFactory {
	public Coffee createCoffee(String type) {
		Coffee coffee = null;
		if("americano".equals(type)) {
			coffee = new AmericanoCoffee();
		} else if("latte".equals(type)) {
			coffee = new LatteCoffee();
		}
	return coffee;
	}
}

Coffee
AmericanCoffee
LatteCoffee

优点:封装了创建对象的过程,可以通过参数直接获取对象,把对象的创建和业务逻辑层分开,避免修改客户代码,实现新产品直接修改工厂类,不需要在原代码种修改

缺点:增加新产品时还是需要修改工厂类的代码,违背了“开闭原则”

扩展

静态工厂

把工厂类中创建对象的功能定义为静态的

public class SimpleCoffeeFactory {
	public static Coffee createCoffee(String type) {
		Coffee coffee = null;
		if("americano".equals(type)) {
			coffee = new AmericanoCoffee();
		} else if("latte".equals(type)) {
			coffee = new LatteCoffee();
		}
		return coffe;
	}
}

在这里插入图片描述
好处是可以直接通过类名调用

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。
目的是使创建对象和使用对象分离,并且客户端总是引用抽象工厂和抽象产品。

在这里插入图片描述结构
1、抽象工厂
2、具体工厂
3、抽象产品
4、具体产品

CoffeeFactory<>
CoffeeStore
Coffee
AmericanCoffee
LatteCoffee
AmericanCoffeeFactory
LatteCoffeeFactory

在这里插入图片描述
优点:

  • 用户只需要知道具体工厂的名称就可得到所要的产品,无需知道产品的具体创建过程
  • 系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行任何修改

缺点:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度

抽象工厂模式

抽象工厂模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构

是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生成多个等级的产品

结构
1、抽象工厂
2、具体工厂
3、抽象产品
4、具体产品

在这里插入图片描述如果要加同一个产品族的话,只需要再加一个对应的工厂类即可,不需要修改其他的类。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/275805.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

雷军的最后一战,就这?

作者 | 魏启扬 来源 | 洞见新研社 2021年3月30日&#xff0c;小米官宣进军电动汽车赛道后的1003天&#xff0c;小米汽车亮相了。 由于是雷军“人生中最后一次重大的创业项目”&#xff0c;押上了雷军“人生所有积累的战绩和声誉”&#xff0c;小米对于造车极为重视&#xff…

hyper-v ubuntu 3节点 k8s集群搭建

前奏 搭建一主二从的k8s集群&#xff0c;如图所示&#xff0c;准备3台虚拟机。 不会创建的同学&#xff0c;可以看我上上篇博客&#xff1a;https://blog.csdn.net/dawnto/article/details/135086252 和上篇博客&#xff1a;https://blog.csdn.net/dawnto/article/details/135…

6、LLaVA

简介 LLaVA官网 LLaVA使用Vicuna(LLaMA-2)作为LLM f ϕ ( ⋅ ) f_\phi() fϕ​(⋅)&#xff0c;使用预训练的CLIP图像编码器 ViT-L/14 g ( X v ) g(X_v) g(Xv​)。 输入图像 X v X_v Xv​&#xff0c;首先获取feature Z v g ( X v ) Z_vg(X_v) Zv​g(Xv​)。考虑到最后一…

SLF4J: Class path contains multiple SLF4J bindings.解决

背景 项目正常运行几年&#xff0c;近期优化调整修复漏洞&#xff0c;依赖升级后cleaninstall 重启发现项目启动失败&#xff0c;访问所有接口都报错404 错误信息 output输出异常信息截图 tomcat 打印异常信息截图 output打印异常信息详情 D:\javaRuanJian\Tomcat\apach…

【IDEA - EasyCode】好物推荐 -> 代码自动生成工具

目录 一、EasyCode 一、EasyCode 只要是与数据库相关的代码都可以通过自定义模板来生成&#xff0c;支持数据库类型与 java 类型映射关系配置。 使用步骤如下&#xff1a; a&#xff09;下载插件 b&#xff09;准备一张表作为生成元数据&#xff0c;例如如下 user 表 c&…

Android Security PIN 相关代码

开发项目遇到一个问题&#xff0c;具体描述及复制步骤如下&#xff1a; 就是开启"Enhanced PIN privacy"(增强的PIN隐私)的时候输入秘密的时候还是会显示数字 如下图&#xff0c;应该是直接是“.” 不应该出现PIN 密码 想要的效果如下图&#xff1a; 设置的步骤如下图…

Springboot实现登录注册

功能&#xff1a;1、实现用户的登录 2、实现用户的注册以及重名的判断 LoginControl&#xff1a; package com.example.demo.controls;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; imp…

Android下载gradle失败解决方法

1、在gradle-wrapper.properties文件中查看自己需要下载gradle什么版本的包和zip路径&#xff08;wrapper/dists&#xff09;。 2、在setting中查看Gradle的保存路径&#xff0c;如下图&#xff1a;C:/Users/Administrator/.gradle&#xff0c;加上第一步的zip路径得到下载grad…

java itext5 生成PDF并填充数据导出

java itext5 生成PDF并填充数据导出 依赖**文本勾选框****页眉**&#xff0c;**页脚****图片**实际图 主要功能有文本勾选框&#xff0c;页眉&#xff0c;页脚&#xff0c;图片等功能。肯定没有专业软件画的好看&#xff0c;只是一点儿方法。仅供参考。 依赖 <!--pdf-->&…

数据结构学习 Leetcode322 零钱兑换

关键词&#xff1a;动态规划 完全背包 记忆化搜索 一个套路&#xff1a; 01背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要逆序遍历完全背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要正序遍历 题目&#xff1a; 方法一&#xff…

CodeWhisperer——轻松使用一个超级强大的工具

CodeWhisperer 简介 CodeWhisperer是亚⻢逊云科技出品的一款基于机器学习的通用代码生成器&#xff0c;可实时提供代码建议。 CodeWhisperer有以下几个主要用途&#xff1a; 解决编程问题&#xff0c;提供代码建议&#xff0c;学习编程知识等等&#xff0c;并且CodeWhisper…

LLM(八)| Gemini语言能力深度观察

论文地址&#xff1a;https://simg.baai.ac.cn/paperfile/fc2138ce-cadb-4a36-b9f7-c4000dea3369.pdf 谷歌最近发布的Gemini系列模型是第一个在各种任务与OpenAI GPT系列相媲美的模型。在本文中&#xff0c;作者对Gemini的语言能力做了深入的探索&#xff0c;做出了两方面的贡献…

微信小程序开发系列-06事件

什么是事件 事件是视图层到逻辑层的通讯方式。事件可以将用户的行为反馈到逻辑层进行处理。事件可以绑定在组件上&#xff0c;当达到触发条件时&#xff0c;就会执行逻辑层中对应的事件处理函数。事件对象可以携带额外信息&#xff0c;如 id, dataset, touches。 事件分类 事…

C实现数组奇数在前偶数在后排序

一、运行结果&#xff1b; 二、源码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现调整函数move_odd_even函数&#xff1b; void move_odd_even(int arr[], int sz) {//初始化变量值&#xff1b;int left 0;int right sz - 1;//循环判断和…

Arduino开发实例-ADS1232高精度24位ADC数据采样

ADS1232高精度24位ADC数据采样 文章目录 ADS1232高精度24位ADC数据采样1、ADS1232介绍2、硬件准备及接线3、驱动实现1、ADS1232介绍 几乎所有的微控制器都带有 ADC 引脚,但它们缺乏高精度。 在很多项目中,需要对模拟量进行高精度的测量,或者被测信号的电压电平不在单片机的…

2022年全国职业院校技能大赛高职组云计算正式赛卷第三场-公有云

2022 年全国职业院校技能大赛高职组云计算赛项试卷 【赛程名称】云计算赛项第三场-公有云 目录 2022 年全国职业院校技能大赛高职组云计算赛项试卷 【赛程名称】云计算赛项第三场-公有云 【任务 1】公有云服务搭建[10 分] 【任务 2】公有云服务运维[10 分] 【任务 3】公有云运维…

【我与Java的成长记】之this引用和构造方法的使用详解

系列文章目录 能看懂文字就能明白系列 C语言笔记传送门 &#x1f31f; 个人主页&#xff1a;古德猫宁- &#x1f308; 信念如阳光&#xff0c;照亮前行的每一步 文章目录 系列文章目录&#x1f308; *信念如阳光&#xff0c;照亮前行的每一步* 前言一、this的使用this引用的特…

机器学习之人工神经网络(Artificial Neural Networks,ANN)

人工神经网络(Artificial Neural Networks,ANN)是机器学习中的一种模型,灵感来源于人脑的神经网络结构。它由神经元(或称为节点)构成的层级结构组成,每个神经元接收输入并生成输出,这些输入和输出通过权重进行连接。 人工神经网络(ANN)是一种模仿生物神经系统构建的…

动态规划08--一和零

题目描述 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的大小&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 思路分析 做到这道题的时候没什么思路&a…

LSTM Siamese neural network

本文中的代码在Github仓库或Gitee仓库中可找到。 Hi, 你好。我是茶桁。 大家是否还记得&#xff0c;在「核心基础」课程中&#xff0c;我们讲过CNN以及LSTM。 卷积神经网络&#xff08;CNN&#xff09;已经在计算机视觉处理中得到广泛应用&#xff0c;不过&#xff0c;2017年…