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

news2024/11/29 2:46:56

文章目录

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

创建型模式

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

包括:
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、具体产品

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深信服AF防火墙配置SSL VPN

防火墙版本&#xff1a;8.0.85 需提前确认防火墙是是否有SSL VPN的授权&#xff0c;确认授权用户数量 1、确认内外网接口划分 2、网络→SSL VPN&#xff0c;选择内外网接口地址 3、SSL VPN→用户管理→新增一个SSL VPN的用户 4、新增L3VPN资源&#xff0c;类型选择Other&…

在用Vite开发时静态图片放哪里,才能保证显示,不出现找不到资源

在用Vite开发时静态图片放哪里 在用Vite开发时静态图片&#xff08;资源&#xff09;放哪里呢 &#xff1f; 如果你想直接全部显示的那么请你把静态资源放到public目录下面&#xff0c;这样你一打包所有的静态资源都会放到打包根目录下。但是此时你在项目中引用的地址一定要是…

微信小程序登录(生成token,token校验)——后端

写在前面&#xff1a;如果想自己开发微信小程序&#xff0c;需要先到微信小程序官方平台注册账号&#xff0c;地址为&#xff1a;https://mp.weixin.qq.com/wxopen/waregister?actionstep1. 登录流程 其中&#xff0c;开发者服务器就是我们的后端服务器&#xff0c;微信接口服…

编程笔记 GOLANG基础 003 Go语言开发环境搭建

编程笔记 GOLANG基础 003 Go语言开发环境搭建 一、安装VSCODE二、安装GO语言主程序 Golang的学习从开发环境搭建开始。本例记录的是WINDOWS平台下使用VSCODE做为开发工具的搭建过程。网上查到的资料都是以前版本的方法&#xff0c;新版Golang发生了一些变化。各位参数环境搭建时…

【c++】

1.定义自己的命名空间myspace&#xff0c;并在myspace中定义一个字符 #include <iostream> #include <cstring> //<><string.h> #include <cstdio> using namespace std; //3.定义自己的命名空间myspace&#xff0c;并在myspace中定义一个字符…

使用PLC 网关采集西门子PLC,提供远程售后服务

实现工业场景下的万物互联离不开对工业自动化设备的数据采集。其中PLC常用的工业现场总线协议就多达数十种&#xff0c;此外各大PLC厂商基本都有各自的私有总线协议。由于现场总线种类繁多各异&#xff0c;传统的工业PLC数据采集一般通过在设备侧部署边缘网关的方式进行&#x…

Flink Kafka[输入/输出] Connector

本章重点介绍生产环境中最常用到的Flink kafka connector。使用Flink的同学&#xff0c;一定会很熟悉kafka&#xff0c;它是一个分布式的、分区的、多副本的、 支持高吞吐的、发布订阅消息系统。生产环境环境中也经常会跟kafka进行一些数据的交换&#xff0c;比如利用kafka con…

美国化妆品FDA认证被强制要求,出口企业该这么办!!!

化妆品FDA认证是进入美国市场的重要准入条件&#xff0c;具备该认证有助于提升产品的市场竞争力和信誉&#xff1b; 目前FDA注册系统已全面开放&#xff0c;从原来的自愿性认证变更为现在的强制性认证&#xff0c;化妆品企业合规日期为2023年12月29日&#xff0c;但是强制处罚…

便携式小型气象站-科普知识

在当今快节奏的生活中&#xff0c;人们对气象信息的关注度越来越高。为了满足这一需求&#xff0c;便携式小型气象站应运而生&#xff0c;成为气象观测的新宠。这款设备不仅方便携带&#xff0c;而且功能齐全&#xff0c;可以随时随地为您提供准确的气象数据。 WX-BXQX8便携式…

git 学习 之一个规范的 commit 如何写

最好的话做一件完整的事情就提交一次

gin框架使用系列之四——json和protobuf的渲染

系列目录 《gin框架使用系列之一——快速启动和url分组》《gin框架使用系列之二——uri占位符和占位符变量的获取》《gin框架使用系列之三——获取表单数据》 上篇我们介绍了如何获取数据&#xff0c;本篇我们介绍一下如何返回固定格式的数据。 一、返回JSON数据 在web开发中…

【贪心】哈夫曼编码Python实现

文章目录 [toc]哈夫曼编码不同编码方式对比前缀码构造哈夫曼编码哈夫曼算法的正确性贪心选择性质证明 最优子结构性质证明 总结 时间复杂性Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;贪心算法 哈夫曼编码 哈夫曼编码是广泛用于数据文件压缩的十分有效的编码…

gitlab请求合并分支

直接去看原文: 原文链接:Gitlab合并请求相关流程_source branch target branch-CSDN博客 --------------------------------------------------------------------------------------------------------------------------------- 入口&#xff1a; 仓库控制台的这两个地方都…

Oracle database 静默安装 oracle12c 一键安装 12.1.0.2

基于oracle安装包中应答文件实现一键安装 注意此安装脚本基于12.1.0.2 安装包 原始安装包结构为两个压缩包 此脚本使用安装包为原始压缩包解压后、 重新封装为一个.zip压缩包 建议在linux 环境下解压重新压缩后 使用该脚本 支持环境: Linux :centerOS 7 oracle :12.1.0.…

力扣精选题

题目: 写出最大数 回答: let count function(a,b){ let num1 a.toString() let num2 b.toString() return (num2num1)-(num1num2) } let last arr.sort(count) let arr [18,20,33,4,5] let num last.join() console.log(last,last) 最终得出最大数字符串: …

某后台管理系统加密参数逆向分析

前言 在我们日常的渗透中经常会遇到开局一个登录框的情况&#xff0c;弱口令爆破当然是我们的首选。但是有的网站会对账号密码等登录信息进行加密处理&#xff0c;这一步不由得阻碍了很多人的脚步。前端的加解密是比较常见的&#xff0c;无论是 web 后台还是小程序&#xff0c…

TransNeXt:稳健的注视感知ViT学习笔记

论文地址&#xff1a;https://arxiv.org/pdf/2311.17132.pdf 代码地址&#xff1a; GitHub - DaiShiResearch/TransNeXt: Code release for TransNeXt model 可以直接在ImageNet上训练的分类代码&#xff1a;GitHub - athrunsunny/TransNext-classify 代码中读取数据的部分修改…

数据驱动与数据安全,自动驾驶看得见的门槛和看不见的天花板

作者 |田水 编辑 |德新 尽管心理有所准备&#xff0c;2023年智能驾驶赛道的内卷程度还是超出了大多数人的预期。 这一年&#xff0c;汽车价格战突然开打&#xff0c;主机厂将来自销售终端的价格压力&#xff0c;传导到下游智驾供应商&#xff0c;于是&#xff0c;市面上出现…

鸿蒙4.0实战应用(ArkTS)-抽奖转盘

构建主界面 在这个章节中&#xff0c;我们将完成示例主界面的开发&#xff0c;效果如图所示&#xff1a; 功能要求&#xff1a; 通过画布组件Canvas&#xff0c;画出抽奖圆形转盘。通过显式动画启动抽奖功能。通过自定义弹窗弹出抽中的奖品。 在绘制抽奖圆形转盘前&#xff…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之线性布局容器Column组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之线性布局容器Column组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Column组件 沿垂直方向布局的容器。 子组件 可以包含子组件。 接…