【设计模式】创建型设计模式

创建型设计模式

文章目录

  • 创建型设计模式
    • 一、概述
    • 二、单例模式
    • 三、工厂模式
      • 3.1 简单工厂模式(静态工厂模式)
      • 3.2 工厂方法模式
      • 3.3 抽象工厂模式
      • 3.3 工厂模式小结
    • 四、原型模式
    • 五、建造者模式

一、概述

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

  • 单例模式(Singleton Pattern)
  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 原型模式(Prototype Pattern)
  • 建造者模式(Builder Pattern)

二、单例模式

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

使用场景:需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多(即:重量级对象),但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源session 工厂等);Spring 默认注入对象都是单例模式的。

单例模式有多种实现方式,这里提供三种实现方式:

实现的选择:一般可用饿汉式,涉及反序列化用枚举,要求懒加载用静态内部类

  1. 饿汉式:无懒加载效果,缺点:无懒加载,无法防止反序列化
public class Singleton {private final static Singleton INSTANCE = new Singleton();private Singleton (){}public static Singleton getInstance() {return INSTANCE;}
}
  1. 枚举实现:确保了单例,且能防止反序列化,缺点:无法懒加载
public enum SingletonEnum {INSTANCE;public void func() {System.out.println("只能通过INSTANCE枚举执行我");}
}
  1. 静态内部类:确保多线程下也能保持单例懒加载,缺点:无法防止反序列化创建对象
public class Singleton {private Singleton() {}private static class SingletonHolder {private final static Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}

三、工厂模式

在工厂模式中,在创建对象时不会对调用方暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。

3.1 简单工厂模式(静态工厂模式)

看一个披萨项目:要便于披萨种类的扩展,要便于维护。

  1. 披萨的种类很多(比如 GreekPizza、CheesePizza 等)
  2. 披萨的制作有 prepare,bake, cut, box
  3. 完成披萨店订购功能PizzaOrder

传统方式:

在这里插入图片描述

	public void orderPizza(String type) {Pizza pizza = null;if ("greek".equals(type)) {pizza = new GreekPizza();} else if ("cheese".equals(type)) {pizza = new CheesePizza();} else if ("paper".equals(type)) {pizza = new PepperPizza();} else {throw new RuntimeException("No such pizza!");}pizza.prepare();pizza.bake();pizza.cut();pizza.box();}

上面设计违反了开闭原则,当需要增加一个披萨种类时,调用端也必须修改代码增加判断逻辑。用简单工厂模式实现,则可以将调用方与披萨接口的实现解耦,代码如下,此时增加品种,调用方也无需修改代码。

public class PizzaFactory {public static Pizza getPizza(String type) {Pizza pizza = null;if ("greek".equals(type)) {pizza = new GreekPizza();} else if ("cheese".equals(type)) {pizza = new CheesePizza();} else if ("paper".equals(type)) {pizza = new PepperPizza();} else {throw new RuntimeException("No such pizza!");}return pizza;}
}
	public void orderPizza(String type) {Pizza pizza = PizzaFactory.getPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();}

3.2 工厂方法模式

披萨项目新的需求:客户在点披萨时,可以点不同口味的披萨,比如 北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦没有胡椒 pizza。

传统方式:将工厂分为北京的和伦敦的,分别生产不同口味的披萨

工厂方法模式:在上个工厂类中,新增两个方法,分别代表北京的披萨和伦敦的披萨,对应方法中再创建不同口味的实现类,这种方式即工厂方法模式。

3.3 抽象工厂模式

模式如其名,抽象工厂即超级工厂,用来进行统一工厂的创建,将分类进一步解耦。

在这里插入图片描述

3.3 工厂模式小结

注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

四、原型模式

原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。需要克隆一个对象时,尽量不要创建新的对象,然后一个个设置值。

  1. Java中可以通过实现Cloneable接口,复写clone方法调用父类Object中的clone方法实现,注意:这种方式对于该类中引用数据类型会进行浅拷贝
  2. 通过序列化与反序列化的方式深拷贝克隆原型对象

在这里插入图片描述

原理结构图说明

  1. Prototype : 原型类,声明一个克隆自己的接口
  2. ConcretePrototype: 具体的原型类, 实现一个克隆自己的操作
  3. Client: 让一个原型对象克隆自己,从而创建一个新的对象(属性一样)

五、建造者模式

建造者模式(Builder Pattern) 又叫生成器模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

建造者模式 是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

主要解决在软件系统中,有时候面临着 “一个复杂对象” 的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

在这里插入图片描述

原理图中,创建过程由 Director 指定,也就是构建 Builder 的整体流程被抽象出来了,当需要根据情况,先执行 C 再执行 B时,只需要更改 Director 中的执行顺序即可。

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

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

相关文章

【MySQL】insert和select单表查询详解(包含大量示例,看了必会)

insert和select 前言正式开始Create全列插入指定列插入多行插入插入失败就更新替换 Retrieveselect语法简介开始查询全列查询指定列查询select后面跟表达式对结果去重条件查询 查询的示例英语不及格的同学及英语成绩 ( < 60 )语文成绩在 [80, 90] 分的同学及语文成绩数学成绩…

spass-二元变量相关分析

基础概念 计算相关系数r&#xff1a;利用样本数据计算样本相关系数&#xff0c;样本相关系数反映了两变量间线性相关程度的强弱。相关系数的取值范围界于-1与1之间&#xff0c;即-1≤r≤1 当0<r ≤ 1&#xff0c;表明变量之间存在正相关关系&#xff1b; 当-1 ≤ r…

4、FFmpeg命令行操作10

音视频处理流程 先看两条命令 ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx264 -s 1280x720 test_1280x720.flv ffmpeg -i test_1920x1080.mp4 -acodec copy -vcodec libx265 -s 1280x720 test_1280x720.mkv ffmpeg音视频处理流程

网络协议入门 笔记一

一、服务器和客户端及java的概念 JVM (Java Virtual Machine) : Java虚拟机&#xff0c;Java的跨平台:一次编译&#xff0c;到处运行&#xff0c;编译生成跟平台无关的字节码文件 (class文件)&#xff0c;由对应平台的JVM解析字节码为机器指令 (010101)。 如下图所示&#xff0…

《Fine-Grained Image Analysis with Deep Learning: A Survey》阅读笔记

论文标题 《Fine-Grained Image Analysis with Deep Learning: A Survey》 作者 魏秀参&#xff0c;南京理工大学 初读 摘要 与上篇综述相同&#xff1a; 细粒度图像分析&#xff08;FGIA&#xff09;的任务是分析从属类别的视觉对象。 细粒度性质引起的类间小变化和类内…

springboot集成nacos并实现自动刷新

目录 1.说明 2.示例 3.自动刷新的注意点 1.说明 springboot项目中存在好多配置文件&#xff0c;比如配置数据信息&#xff0c;redis信息等等&#xff0c;配置文件可以直接放在代码&#xff0c;也可以放在像nacos这样的组件中&#xff0c;实现动态的管理&#xff0c;修改配置…

Ubuntu20.0中安装Gradle

下载Gradle到temp文件夹 wget https://services.gradle.org/distributions/gradle-8.3-bin.zip -P /tmp 然后解压文件到/opt/gradle目录 sudo unzip -d /opt/gradle /tmp/gradle-8.3.zip 配置Gradle环境变量 接下来我们会创建一个gradle.sh文件来保存Gradle的环境变量 sudo…

JDK1.5 新特性【泛型】

前言 泛型在 JavaSE 阶段是学习过的&#xff0c;但是毕竟处理定义一些简单的集合就很少用到它了&#xff0c;至于最近 Flink 中遇到的 泛型方法&#xff0c;更是感觉闻所未闻&#xff0c;以及源码中加在接口、方法、类前的各种 <T,V> 让我实在自觉羞愧&#xff0c;于是今…

SpringMVC总结

SpringMVC简介 简介 SpringMVC是一款基于Servlet API构建的原始Web框架&#xff0c;从一开始就包含在Spring Framework中。正式名称“Spring Web MVC”来自其源模块的名称&#xff08; spring-webmvc &#xff09;&#xff0c;但它通常被称为“Spring MVC”。 调用流程 接收数…

3.6-Dockerfile语法梳理及最佳实践

WORKDIR是设置当前docker的工作目录 ADD 和 COPY 为了将本地的一些文件添加到docker image里面&#xff0c;ADD 和 COPY的作用特别像&#xff0c;但是ADD 和 COPY还有一些区别&#xff0c;ADD不仅可以添加本地文件到docker里面&#xff0c;还可以将文件在添加到docker image里面…

4.Pod详解【四】

文章目录 4. Pod详解4.1 Pod介绍4.1.1 Pod结构4.1.2 Pod定义 4.2 Pod配置4.2.1 基本配置4.2.2 镜像拉取4.2.3 启动命令4.2.4 环境变量4.2.5 端口设置4.2.6 资源配额 4.3 Pod生命周期4.3.1 创建和终止4.3.2 初始化容器4.3.3 钩子函数4.3.4 容器探测4.3.5 重启策略 4.4 Pod调度4.…

C++算法入门练习——树的带权路径长度

现有一棵n个结点的树&#xff08;结点编号为从0到n-1&#xff0c;根结点为0号结点&#xff09;&#xff0c;每个结点有各自的权值w。 结点的路径长度是指&#xff0c;从根结点到该结点的边数&#xff1b;结点的带权路径长度是指&#xff0c;结点权值乘以结点的路径长度&#x…