当前位置: 首页 > news >正文

Java设计模式总结

《武林外传》老白曾经说过这样一句话。高手就是手里无刀,心中也无刀。 类似于设计模式,你不知不觉中已经融进你的代码中了,但你并不知已经运用了。下面我总结几个我觉得比较常用的设计模式。

1:设计模式分类

总体来说设计模式分为三大类:

创建型模式, 共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式, 共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式, 共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

大家没有必要死记硬背哪一种模式属于哪一种类型,面试如果问到,因为不会背而挂,只能说这家公司不去也罢。

我们需要真正理解,为什么工厂方法模式也是创建型模式,因为它是一个factory,他创建一个对象供你使用。又比如适配器模式为什么是结构型模式,它是不是从”顺序性编码“变成了”分支形编码“,改变了代码的结构。所以你需要真正理解每一种设计模式,做到不自觉的运用到你的代码中去。

2:单例模式

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

//懒汉 线程不安全
class SingletonDemo1 {private SingletonDemo1(){}private static SingletonDemo1 instance = null;public static SingletonDemo1 getInstance() {if (instance == null) {instance = new SingletonDemo1();}return instance;}
}//懒汉 线程安全 直接加锁
class SingletonDemo2 {private SingletonDemo2() {}private static SingletonDemo2 instance = null;public static synchronized SingletonDemo2 getInstance() {if (instance == null) {instance = new SingletonDemo2();}return instance;}
}// Double Check
public class SingletonDemo2 {private volatile static Singleton instance;private Singleton() {}public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}//饿汉 线程安全
class SingletonDemo3 {private SingletonDemo3() {}private static SingletonDemo3 instance = new SingletonDemo3();public static SingletonDemo3 getInstance() {return instance;}
}//内部类 线程安全,并且懒加载
class SingletonDemo4 {private SingletonDemo4() {}private static class InnerSingletonDemo4 {private static final SingletonDemo4 instance = new SingletonDemo4();}public static final SingletonDemo4 getInstance() {return InnerSingletonDemo4.instance;}
}// 枚举方式。最为推荐的一种方式
public enum SingletonDemo5 {INSTANCE;public void doSomeThing() {}
}

3: 适配器模式

举个例子,比较插头的电源为110v,但是我们现在想要220v的电源。所以我们就可以用适配器模式,使这个类符合我现有的要求。

同样,在编写JAVA程序时,我们可能会遇到这样一种情况:我们需要一个类A来实现接口B,但是类A并没有实现接口B中的所有方法,而类A是不能被改变的,这时我们可以创建一个类C,它继承类A并实现接口B,这个类C就是一个适配器。适配器中的代码将接受你所拥有的接口,并产生你所需要的接口。适配器模式有两张:类适配器模式和对象适配器模式。

// 假设这个规定电源为220v
interface A {void method220v();}//这个类实现的为110v的方法
class B {void method110v() {System.out.println("110v");}
}// 适配为既可以110v,也可以220v
class C extends B implements A {@Overridepublic void method220v() {System.out.println("220v");}
}

4:装饰着模式

装饰者模式通过组合的方式扩展对象的特性,这种方式允许我们在任何时候对对象的功能进行扩展甚至是运行时扩展,而若我们用继承来完成对类的扩展则只能在编译阶段实现,所以在某些时候装饰者模式比继承(inheritance)要更加灵活。

所谓装饰者,实际上就是将装饰的内容的以零部件的形式构建起来,然后经过组装形成一个一个新的逻辑内容,动态而灵活的组建逻辑性能。

// 形状
Shape circle = new Circle();// 加了红色的形状
Shape redCircle = new RedShapeDecorator(new Circle());// 加了红色的长方形
Shape redRectangle = new RedShapeDecorator(new Rectangle());

5:策略模式

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

应用实例:

  • 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。

  • 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

  • JAVA AWT 中的 LayoutManager。

优点:

  • 算法可以自由切换。

  • 避免使用多重条件判断。

  • 扩展性良好。

缺点:

  • 策略类会增多。

  • 所有策略类都需要对外暴露。

使用场景:

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

  • 一个系统需要动态地在几种算法中选择一种。

  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。举一个例子:很简单的一个例子。比如人,人分为男人,女人,甚至不清楚性别的人。但这三种类型的人,都有不同的行为。那么我们在描述这些不同行为的时候,一般我们做法就是如下:

if (male) {//...
} else if (female) {//...
} else {//...
}

类似如上。很多个if,else进行嵌套。这样非常的难看,不优雅。如果我们用策略模式替换,会怎么样。

  • 第一步,定义一个Person类接口

  • 第二步定义person的继承类,如男人,女人等等

  • 第三步定义一个enum类,表示可选择性。

  • 最后一步定义一个策略选择器

public interface Person {void executeStrategy();
}public class MalePerson implements Person {public void executeStrategy() {System.out.println("我是男性");}
}public class FemalePerson implements Person {public void executeStrategy() {System.out.println("我是女性");}
}public class UnknownPerson implements Person {public void executeStrategy() {System.out.println("未知性别");}
}public enum SexEnum {MALE("male", "男性"),FEMALE("female", "女性"),UNKNOWN("unknown", "未知");private String code;private String sex;SexEnum(String code, String sex) {this.code = code;this.sex = sex;}
}// 这块在实际开发中,我们会用factory结合spring来做这块逻辑
public class ContextStrategy {private MalePerson malePerson = new MalePerson();private FemalePerson femalePerson = new FemalePerson();private UnknownPerson unknownPerson = new UnknownPerson();public Person getPersonStrategy(SexEnum sexEnum) {if ("male".equals(sexEnum.getCode())) {return malePerson;} else if ("female".equals(sexEnum.getCode())) {return femalePerson;} else {return unknownPerson;}}
}public class Main {public static void main(String[] args) {ContextStrategy strategy = new ContextStrategy();strategy.getPersonStrategy(**SexEnum.MALE**).executeStrategy();strategy.getPersonStrategy(**SexEnum.FEMALE**).executeStrategy();strategy.getPersonStrategy(**SexEnum.UNKNOWN**).executeStrategy();}
}// 结果如下:
// 我是男性
// 我是女性
// 未知性别

其实我们可以看到。策略选择器是传入一个Enum类,然后根据传入Enum的不同,选择了不同的继承类。从而实现了if else。优雅的过渡。可以看到,代码非常的优雅易懂,主代码,没有if else分支。但同时代码量多了起来。不过也很容易维护。

在实际项目中,我们一般会使用工厂模式 + 策略模式一起使用来达到减少if else的操作,策略模式在实际使用中非常的多,建议同学们务必掌握。

6:责任链模式

// 校验器接口
public interface Validator<T> {Validator<T> next();boolean handle(T t) throws FordealException;
}public class BasicParameterValidator implements Validator<ValuationWO> {@Autowiredprivate Validator<ValuationWO> tokenValidator;@Overridepublic Validator<ValuationWO> next() {return tokenValidator;}@Overridepublic boolean handle(ValuationWO valuationWO) throws Exception {return next().handle(valuationWO);}
}

最后

以上举了几个简单的例子,做一个抛砖引玉,还是希望同学们可以花一点时间,去了解下比较常用的设计模式。不需要背下来,多看看别人写的代码,然后尝试去模仿,慢慢的,你就会发觉,你就开始融会贯通了。做到手里无刀,心中也无刀,但实际上又快有准。

文章转载自:程序员博博

原文链接:https://www.cnblogs.com/wenbochang/p/8834587.html

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

相关文章:

Java设计模式总结

《武林外传》老白曾经说过这样一句话。高手就是手里无刀&#xff0c;心中也无刀。 类似于设计模式&#xff0c;你不知不觉中已经融进你的代码中了&#xff0c;但你并不知已经运用了。下面我总结几个我觉得比较常用的设计模式。 1&#xff1a;设计模式分类 总体来说设计模式分为…...

小米路由器如何设置去广告功能,如何设置小米路由器的自定义Hosts(小米路由器如何去除小米广告、去除小米电视盒子开屏广告、视频广告)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 实现方案 📒📝 操作步骤📝 注意事项⚓️ 相关链接 ⚓️📖 介绍 📖 小米设备的广告一直是用户头疼的问题,无论是开屏广告、应用内广告还是系统广告,都影响了用户体验。本文将详细介绍如何通过小米路由器实现去除广告…...

HCIP-Datacom-ARST自选题库__EBGP【18道题】

一、单选题 1.在排除EBGP邻居关系故障时&#xff0c;你发现两台直连设备使用Loopback口建立连接&#xff0c;故执行display current-configurationconfiguration bgp查看peer ebgp-max-hop hop-count的配置&#xff0c;下列哪项说法是正确的? hop-count必须大于2 hop-count…...

TypeScript算法每日一题:两数之和(167)

作者&#xff1a;前端小王hs 阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主 题库&#xff1a;力扣 题目序号&#xff1a;167&#xff08;简单&#xff09; 题目&#xff1a; 给你一个下标从1开始的整数数组 numbers &#xff0c;该数组已按非…...

用docker搭建的Vulfocus镜像管理界面没有镜像可以拉取解决办法

ps&#xff1a;截止到今天2023.4.2&#xff0c;kali和vps的docker拉取的vulfocus镜像会有版本的区别&#xff0c;虽然都是拉取的最新版&#xff0c;vps上镜像为3个月以前&#xff0c;kali上为16个月以前&#xff0c;所以在修改 views.py 文件时&#xff0c;可能会发现文件内容不…...

CSPM.pdf

PDF转图片 归档&#xff1a;...

多个短视频剪辑成一个视频:四川京之华锦信息技术公司

多个短视频剪辑成一个视频&#xff1a;创作中的艺术与技术 在数字时代&#xff0c;短视频以其短小精悍、内容丰富的特点&#xff0c;迅速成为社交媒体上的热门内容形式。然而&#xff0c;有时单一的短视频难以完全表达创作者的意图或满足观众的观赏需求。因此&#xff0c;将多…...

算法第三天力扣第69题:X的平方根

69. x 的平方根 (可点击下面链接或复制网址进行做题) https://leetcode.cn/problems/sqrtx/https://leetcode.cn/problems/sqrtx/ 给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被…...

异常处理。

异常 是指程序运行中出现了错误。 捕获异常&#xff1a; 对bug进行提醒&#xff0c;使整个程序继续运行。 捕获所有异常&#xff1a; try:#可能出错的代码 except:如果出现异常执行的代码 可以输出异常的类型&#xff1a; try:a1bhuishprint(ab) except Exception as i:…...

MySQL—函数(介绍)—字符串函数(基础)

一、引言 提到函数&#xff0c;在SQL分类中DQL语句中有一个聚合函数&#xff0c;如COUNT()、SUM()、MAX()等等。这些都是一些常见的聚合函数&#xff0c;而聚合函数只是函数的一种&#xff0c;接下来会详细的学习和介绍一下函数的应用场景和以及 mysql 当中文件的函数有哪些。 …...

CTF本地靶场搭建——静态flag题型的创建

静态flag题型的创建 首先这里要说的是静态flag和动态flag。 在CTF&#xff08;Capture The Flag&#xff09;比赛中&#xff0c;静态flag的使用通常与特定的赛制或题目类型关联&#xff0c;而不是直接与题型绑定。静态flag意味着这些flag是预先设定好的&#xff0c;不会随比…...

基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能(五)

上一篇&#xff1a;搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL&#xff08;四&#xff09; 下一篇&#xff1a;基于Django的博客系统之增加类别导航栏&#xff08;六&#xff09; 功能概述 添加搜索框用于搜索博客。 需求详细描述 1. 添加搜索框用于搜索博客 描…...

开源VS闭源:大模型发展路径之争,你站哪一派?

文章目录 引言一、数据隐私1.1开源大模型的数据隐私1.2 闭源大模型的数据隐私1.3 综合考量 二、商业应用2.1 开源大模型的商业应用2.2 闭源大模型的商业应用2.3 商业应用的综合考量 三、社区参与3.1 开源大模型的社区参与3.2 闭源大模型的社区参与3.3 综合考量 结论 引言 在人…...

Python | Leetcode Python题解之第115题不同的子序列

题目&#xff1a; 题解&#xff1a; class Solution:def numDistinct(self, s: str, t: str) -> int:m, n len(s), len(t)if m < n:return 0dp [[0] * (n 1) for _ in range(m 1)]for i in range(m 1):dp[i][n] 1for i in range(m - 1, -1, -1):for j in range(n …...

STM32高级控制定时器应用之检测输入PWM周期和占空比

目录 概述 1 PWM 输入模式 1.1 原理介绍 1.2 应用实例 1.3 示例时序图 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM占空比函数 3.2 输入捕捉回调函数 4 功能测试 4.1 测试软件框架结构 4.2 实验实现 4.2.1 测试实…...

[AI Google] 三种新方法利用 Gemini 提高 Google Workspace 的生产力

Workspace 侧边栏中的 Gemini 现在将使用 Gemini 1.5 Pro&#xff0c;新的 Gemini for Workspace 功能即将登陆 Gmail 移动应用&#xff0c;等等。 Gemini for Google Workspace 帮助个人和企业更好地利用 Google 应用——从在 Gmail 中撰写邮件到在 Sheets 中组织项目计划。过…...

【U-Net验证】逐元素乘积将特征投射到极高维隐式特征空间的能力

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需使用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言网络结构编码结构解码结构代码 实验实验设置w/o-ReLU的性能比较with-ReLU的性能比…...

快团团大团长帮卖如何导出单个团购的订单?免费教程教你怎么做!

一、小程序端如何导出单个团购的订单&#xff1f; 进入团购页面&#xff0c;在订单管理——订单导出中&#xff0c;点击订单数据表格&#xff0c;可导出到邮箱&#xff0c;或通过在浏览器中查看下载链接 二、电脑端如何导出单个团购的订单&#xff1f; 1、如何自定义选择订单信…...

services层和controller层

services层 我的理解&#xff0c;services层是编写逻辑代码语句最多的一个层&#xff0c;非常重要&#xff0c;在实际的项目中&#xff0c;负责调用Dao层中的mybatis&#xff0c;在我的项目中它调用的是这两个文件 举例代码如下 package com.example.sfdeliverysystem.servic…...

Pycharm编辑器下自定义模块导入报错:no module named问题

相信很多使用pycharm 社区版编写python 程序的初学者都会遇到这样一个看似简单但是一时半刻找不到解决头绪的问题&#xff1a; 在同个目录下导入自己编写的模块到主程序的过程中&#xff0c;直接import的时候会报错&#xff1a;ModuleNotFoundError。 通过各种方法尝试以后还是…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...