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类型的变量instanceprivate 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类型的变量instanceprivate 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类型的变量instanceprivate 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类型的变量instanceprivate 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.hqwc.cn/news/305458.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是SNP SAP云端数据集成解决方案?

SNP SAP云端数据集成解决方案旨在充分利用云计算的灵活性和可伸缩性&#xff0c;以实现更低的成本维护和更快速的决策制定能力。该解决方案通过使用人工智能和机器学习实现高级分析&#xff0c;使用户能够快速做出明智的、数据驱动的决策。通过将数据集成到云端&#xff0c;企业…

vscode无法连接服务器

1.服务器问题 2.网络配置问题 重启服务器或者确认服务器操作无误 C:\Users\Alice\.ssh\config

C# 常用数据类型及取值范围

1.常见数据类型和取值范围 序号数据类型占字节数取值范围1byte10 到 2552sbyte1-128 到 1273short 2-32,768 到 32,7674ushort20 到 65,5355int4-2,147,483,648 到 2,147,483,6476uint40 到 4,294,967,2957float41.5 x 10−45 至 3.4 x 10388double85.0 10−324 到 1.…

Qt学习:Qt的意义安装Qt

Qt 的简介 QT 是一个跨平台的 C图形用户界面应用程序框架。它为程序开发者提供图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正地组件编程。 支持平台 xP 、 Vista、Win7、win8、win2008、win10Windows . Unix/Linux: Ubuntu 等…

Mybatis行为配置之Ⅱ—结果相关配置项说明

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL 文章目录 专栏精选引言摘要正文autoMappingBehaviorautoMappingU…

C++系列-附录-windows下安装C++环境

C系列-附录-windows下安装C环境 在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 参考 Windows搭建C编程环境(VSCodeMingw-w64) C编译器有哪些 C编译器简介 常见的C编译器 C编译器是将C源代码翻译成可执行程序的工具。以下是一些常见的C编译器&…

How to Develop Word Embeddings in Python with Gensim

https://machinelearningmastery.com/develop-word-embeddings-python-gensim/ 本教程分为 6 个部分;他们是&#xff1a; 词嵌入 Gensim 库 开发 Word2Vec 嵌入 可视化单词嵌入 加载 Google 的 Word2Vec 嵌入 加载斯坦福大学的 GloVe 嵌入 词嵌入 单词嵌入是一种提供单词的…

YOLOv8算法优化:解决YOLOv8无法打印计算量(GFLOPs)的问题点

💡💡💡本文内容:解决YOLOv8无法打印计算量的问题点 💡💡💡本文提供:1)训练阶段自动打印计算量;2)提供离线打印计算量的代码; 1.计算量介绍 FLOPS:注意S是大写,是 “每秒所执行的浮点运算次数”(floating-point operations per second)的缩写。它常被用…

SpringBoot多线程与任务调度总结

一、前言 多线程与任务调度是java开发中必须掌握的技能&#xff0c;在springBoot的开发中&#xff0c;多线程和任务调度变得越来越简单。实现方式可以通过实现ApplicationRunner接口&#xff0c;重新run的方法实现多线程。任务调度则可以使用Scheduled注解 二、使用示例 Slf…

12.28网络流,残留网络,增广路,最大流最小割定理

网络流 概念 是指在一个每条边都有容量的有向图分配流&#xff0c;使一条边的流量不会超过它的容量。通常在运筹学中&#xff0c;有向图称为网络。顶点称为节点而边称为弧。一道流必须匹配一个结点的进出的流量相同的限制&#xff0c;除非这是一个源点──有较多向外的流&…

SAP VA01 创建带wbs号的销售订单包 CJ067的错误

接口错误提示如下 SAP官方 CJ067 124177 - VA01: CJ067 during WBS acct assgmt with a different business area S4的core 刚好能用上 实施 这个note后成功

一个注解实现分布式锁

1、原始写法 我们平常使用redisson的分布式锁是怎么做的&#xff1f; 是不是基本都用的这个模板&#xff0c;既然是模板&#xff0c;那为何不把他抽出来呢&#xff1f; // 尝试加锁&#xff0c;最多等待100秒&#xff0c;上锁以后10秒自动解锁 boolean res lock.tryLock(10…