Java进阶(二):Java设计模式

目录

设计模式

一.建模语言

二.类之间的关系

1.依赖关系

2.关联关系

3.聚合关系

4.组合关系

5.继承关系

6.实现关系

三.面向对象设计原则

单一职责原则

开闭原则

里氏替换原则

依赖倒置

接口隔离原则

迪米特原则

组合/聚合(关联关系)复用原则

四.23种设计模式

五.单例模式(只创建一个对象)

六.工厂模式

简单工厂模式(一个工厂对应多类产品)

工厂方法模式(一个工厂对应一类产品)

抽象工厂(一个工厂对应多类商家工厂)

七.原型模式

八.代理模式

九.模板方法模式

十.策略模式


设计模式

设计模式产生背景

设计模式概念首先起源于建筑领域,1990在软件领域也诞生设计模式概念。

直到 1995 年,艾瑞克·伽马(ErichGamma)、理査德·海尔姆(Richard Helm)、拉尔夫·约翰森(Ralph Johnson)、约翰·威利斯迪斯(JohnVlissides),在《设计模式:可复用面向对象软件的基础》中收纳总结了23种设计模式。

什么是设计模式?

        在长期编程的过程中,针对某一类问题经过反复的优化,最终总结出一个固定的解决方案,这些方案经过反复的使用,具有普遍性。

为什么要学习设计模式?

①学习设计模式就是学习好的编程思想,学习前辈们的经验。

②可以提高程序员的思维能力、编程能力和设计能力。

③使程序设计更加标准化、使软件开发效率大大提高。

④使设计的代码可重用性高、可扩展性提高。

⑤能够更好的去理解源码架构。


一.建模语言

        统一建模语言(Unified Modeling Language,UML),是一套软件设计和分析的语言工具

用图形化的方式,记录表示类与类类与接口接口与接口之间的关系, 一般把图形化方式也称为UML类图.

类图中两个基本的要素:

1.类:是对具有相同属性和行为的一组对象的抽象描述

2.接口:是一种特殊的类,它具有类的结构但不可被实例化,只可以被子类实现。


二.类之间的关系

1.依赖关系

        在一个类中的方法,把另一个类作为参数进行使用,具有临时性,方法执行结束后,依赖关系就不存在了。

        一般把xxx类用到了xxx类,这种关系,称为依赖关系,也称为 use-a关系。例如:下图的人与手机的关系,人类中的方法call()中的参数MobilePhone mp就是作为依赖关系。方法结束,依赖关系结束。用虚线箭头表示。

2.关联关系

是一种has-a的关系 ,xxx 有 xxx

在一个类中,把另一个当做自己的成员。用实心三角实线箭头表示。

有单向关联,双向关联,自关联,一对一关联,一对多关联。

关联关系根据强弱又分为:聚合关系和组合关系。

3.聚合关系

聚合关系也是一种关联关系,是强关联关系,是一种整体和部分的关系

学校包含老师, 即使学校不存在了, 老师可以依然独立的存在。

在 UML 类图中,聚合关系可以用带空心菱形的实线来表示,菱形指向整体

4.组合关系

聚合关系也是一种关联关系, 是一种整体和部分的关系, 是一种更强烈的关联关系。

头和嘴关系,头如果不在了,嘴也会跟着销毁。

在 UML 类图中,组合关系用带实心菱形的实线来表示,菱形指向整体

5.继承关系

        继承关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的

关系,是一种继承关系,是 is-a 的关系。

在 UML 类图中,继承关系用带空心三角箭头的实线来表示,箭头从子类指向父类

6.实现关系

        实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接

口中所声明的所有的抽象操作。

在 UML 类图中,实现关系使用带空心三角箭头的虚线来表示,箭头从实现类指向接口


三.面向对象设计原则

单一职责原则

        一个类只负责某一个具体功能,细化类的粒度。比如:Person类只负责关于人的信息,Address类只负责关于地址的信息。


开闭原则

对修改关闭,对扩展开放(不修改,多使用多态的思想)

尽可能的在扩展功能时,不要修改已有的代码,尽可能扩展一个新的类来实现新功能。


里氏替换原则

        继承优势: 提高代码复用性,子类继承父类的功能,提高代码的扩展性,子类还可以扩展自己的功能,不影响其他类,重写父类方法。

        继承劣势: 继承使得类的体系结构变得复杂了

里氏替换:首先时由里斯科夫女士提出的。

        其次是关于继承使用的,当子类继承了父类后, 在使用时,用子类替换父类后,要确保父类中的功能不受影响。(子类重写父类方法时,不得改变改变方法的结果)

主要的思想: 就保证程序的稳定性。


依赖倒置

面向抽象编程,不要面向具体的实现编程。

具体实现应该依赖抽象层 (使用多态,抽象层用来表示,定义--> 具体的由子实现类实现)


接口隔离原则

        不要把所有的功能都定义到一个总的接口中,应该把不同的种类的功能,定义在不同的接口中,让实现类,根据自己的需要去灵活的选择。(不同功能,不同接口)


迪米特原则

只跟朋友联系,不跟"陌生人”说话。

        在程序间相互调用时,如果两个类直接没有直接联系,但是想相互调用,可以通过第三方进行转发调用。(两个类没有直接联系,通过第三方将两者联系,如:明星与粉丝,通过经纪人交流

降低模块之间的耦合度。


组合/聚合(关联关系)复用原则

        继承使得类的体系变得复杂, 如果我们只是想使用某个类中的方法时,也可以优先选择关联关系/ 依赖关系 降低类与类之间的耦合度


四.23种设计模式

设计模式分为3大类
        根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式 3 种。
创建型模式 :用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。提供了
、原型、 工厂方法 、抽象工厂、建造者 5 种创建型模式。
结构型模式 :用于描述如何将类或对象按某种布局组成更大的结构,提供了代理、适配器、桥接、
装饰、外观、享元、组合 7 种结构型模式。
行为型模式 :用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及
怎样分配职责。提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问
者、备忘录、解释器 11 种行为型模式。

五.单例模式(只创建一个对象)

在一个项目中,如何确保一个类始终只有一个对象

特点:

1. 单例类只有一个实例对象;(虽然多次创建,但只能产生一个)
2. 该单例对象必须由单例类自行创建;(在单例类内部,在第一次使用时才创建)
3. 单例类对外提供一个访问该单例的全局访问点;(需要提供一个公共的方法)

单例模式通常两种实现 

①饿汉式单例单例模式中的饿汉式(急切式单例) 在加载此类时,就已经将唯一的一个对象创建出来。

好处:不会存在线程安全问题。

不足: 在类加载时,就会创建单例对象,有可能一段时间内还用不到它。

public class MyWindow {//在内部自己创建的一个单例对象private static MyWindow myWindow = new MyWindow();private MyWindow() {}/*对外提供这唯一的对象*/public static MyWindow getMyWindow() {return myWindow;}
}

懒汉式单例:在类加载时,并没有创建单例对象,在第一次获取单例对象时,才去创建了单例对象。

好处: 类加载时先不创建,在第一次使用获取时才会创建

不足: 会出现线程安全问题加锁解决(synchronized锁)

※ 双重检索 + volatile(可见性,避免重排序)

例如:A  a = new  A();

创建对象这一条语句编译为指令时,可以分为三个指令顺序:

1. new 申请空间

2. 调用构造方法初始化对象

3. 把对象地址赋给引用变量

        如果按照这个正常的顺序执行,是没有问题的,但是执行时,如果2,3条指令顺序发生变化,导致把没有初始化完成的对象地址返回了,拿去使用了,这么做会出问题,因为对象没有初始化完成。所有需要使用volatile关键修饰单例成员变量,确保对其赋值时,指令不重新排序。

public class MyWindow {private volatile static MyWindow myWindow;public static MyWindow getMyWindow() {//第一重检索,隔绝后面大量的线程进入if (myWindow == null) {//加锁,只能一个一个进入synchronized (MyWindow.class) {//第二重检索,隔绝前面少量的线程进入if (myWindow == null) {myWindow = new MyWindow();}}}return myWindow;}
}


六.工厂模式

        解决的就是在项目将创建对象和使用对象分离的问题,(结合Spring),如何更好的组织类与类之间的关系。

简单工厂模式(一个工厂对应多类产品)

简单工厂并不是一种设计模式,违背了开闭原则主要是引出工厂方法抽象工厂模式

涉及的角色:

工厂角色: 根据我们的需求,创建对应的对象。

抽象产品: 具体产品的抽象,具体产品实现 / 继承抽象产品,可以使用上层的抽象父类,表示任意的子类对象。

具体产品: 具体的对象。

优点: 创建对象和使用对象分离了。

缺点: 只能创建实现了同一个父类 / 接口的子类对象, 扩展新的类型,需要修改工厂,违背了开闭原则。

适合简单的,子类较少的场景。

工厂方法模式(一个工厂对应一类产品)

        由于简单工厂中,一个工厂,可以造同一类型的所有具体产品,导致简单工厂比较复杂,扩展一个新类型时,需要修改工厂代码。

        工厂方法模式,为工厂也进行抽象,并且为同类型每个具体产品都创建了一个具体的工厂。

        每一个工厂负责创建一个具体的产品(类型)对象,这样扩展一个新的产品,与之对应就要扩展一个产品工厂,就不需要修改工厂,遵守了开闭原则,单一职责原则。

好处: 遵守了开闭原则。

不足: 类的数量增多了。

抽象工厂(一个工厂对应多类商家工厂)

        如:一个工厂可分为小米工厂,华为工厂。小米工厂可造汽车,手机。华为工厂可造汽车,手机。

        工厂方法模式,是按照产品类型进行分类的,一类产品,对应一类工厂,不同类型产品之间,相互隔离的。例如: 华为和小米,既要汽车,又要造手机,都是属于同一家的产品,但是工厂方法这种设计,同一个公司产品与产品之间没有联系。

        抽象工厂模式对工厂重新进行分类,以公司为单位进行工厂的抽象(提取),一个工厂内,可以创建不同的产品,这样我们就可以创建出像华为工厂,小米工厂这样的具体工厂,一个工厂内,可以创建不同公司的各种产品。


七.原型模式

        在某些场景下,为(解决的问题:)避免自己手动的new对象,我们可以使用对象克隆方式,创建并返回一个新的对象。这种克隆新对象的效率比我们自己new的效率要高。

对象克隆实现方式有两种:

1.实现Cloneable接口,重写clone()

2.使用对象序列化 反序列化重新生成对象

注意深克隆和浅克隆问题。


八.代理模式

        早在spring aop思想中,已经用到了代理思想。在不修改原来代码的前提下,为我们方法添加额外的功能。通过代理对象帮助我们进行调用。

        有些时候,目标对象(汽车厂)不想或不能直接与客户打交道,通过代理对象进行访问,代理对象可以保护目标对象,对目标对象功能进行扩展,降低了模块之间的耦合度。

涉及到三个主题:

抽象主题: (抽取的功能,让目标对象进行实现,以及代理对象进行实现)

具体主题: 真正要实现功能的类。

代理对象

代理模式实现方式又有两种:

1.静态代理

        创建一个代理类,代理实现与具体对象实现相同的接口 / 抽象类,重写抽象方法。还有一个成员变量,可以用接收具体的主题,在代理类中重写的抽象方法中调用真实主题方法,这样就可以在调用之前和之后添加额外的功能。

不足: 一个代理对象,只能代理一个接口类型的对象,不灵活。

2.动态代理

只需要写一次代理类,就可以通过反射机制动态获得类的信息,可以为任何类提供代理功能。

动态代理实现分为两种:

①jdk代理

        jdk代理实现是通过反射机制实现的, 目标类必须要实现一个接口,通过接口动态获得目标类中的信息。

②cglib代理

        是spring中提供的一种代理技术,目标类可以不实现任何接口,采用字节码生成子类的方式,对方法进行拦截,实现机制不同。

注意:cglib不能代理final修饰的类以及fnal和static修饰的方法。

        目前spring中两种动态代理都支持,如果目标类没有实现接口,默认使用cglib代理,如果目标类有实现接口,采用jdk代理。


九.模板方法模式

        模版方法模式,是在一个类中,定义好一个算法骨架,设定好实现步骤,把一些公共的通用的在父类中实现,然后将一些不确定的实现在具体的子类中实现。

        例如,去银行办理业务一般要经过以下 4 个流程:取号、排队、办理具体业务、对银行
工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样
的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,
可以延迟到子类中实现。

结构:

抽象类: 负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。

模版方法: 定义好执行顺序的算法骨架,确定好执行流程顺序。

抽象方法: 不确定的功能,定义为抽象的,交给子类实现。

具体方法: 都一样的公共的通用的方法,在抽象父类中实现。

具体子类: 实现抽象类中的抽象方法的具体类,有不同的实现方式,就可以用多个子类。

        new 具体子类对象,用具体子类对象调用模版方法,把父类中具体方法与自己实现的抽象方法一起执行。

        将变化部分定义为抽象的,让子类去扩展实现,满足开闭原则,适合流程相对比较固定的,其中有变化的场景。

十.策略模式

        将不同的实现算法进行封装,将功能的实现与使用相分离。(多选一策略)在使用时,可以用不同的策略实现类进行替换。重点用到的知识点:继承,多态。

结构

抽象类:抽象方法

具体实现类(多个实现类实现抽象类的抽象方法,在多个实现类中多选一

环境类(使用者)

 感谢你的阅读与关注,如有问题欢迎探讨!💓

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

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

相关文章

双层Git管理项目,github托管显示正常

双层Git管理项目,github托管显示正常 背景 在写React项目时,使用Next.js,该项目默认由git托管。但是我有在项目代码外层记笔记的习惯,我就在外层使用了git托管。 目录如下 code 层内也有.git 文件,对其托管。 我没太在意&…

群晖docker获取私有化镜像http: server gave HTTP response to HTTPS client].

群晖docker获取私有化镜像提示http: server gave HTTP response to HTTPS clien 问题描述 层级时间用户事件Information2023/07/08 12:47:45cxlogeAdd image from xx.xx.31.240:1923/go-gitea/gitea:1.19.3Error2023/07/08 12:47:48cxlogeFailed to pull image [Get "http…

机器学习:支持向量机

支持向量机(Support Vector Machine)是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的广义线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。 假设两类数据可以被 H x : w T x…

相互作用感知的蛋白-小分子对接模型 - Interformer 评测

Interformer 是一个应用于分子对接和亲和力预测的深度学习模型,基于 Graph-Transdormer 架构的模型,利用相互作用(氢键、疏水)感知的混合密度网络(interaction-aware mixture den sity network, MDN&#x…

如果我想设计一款复古风格的壁纸,应该选什么颜色?

设计复古风格的壁纸时,选择合适的颜色是营造怀旧和经典氛围的关键。复古风格通常使用一些温暖、柔和且带有岁月痕迹的色调。以下是一些适合复古风格壁纸的颜色选择和搭配建议: 一、复古风格的主色调 棕色系: 特点:棕色是复古风格的…

AI 浪潮席卷中国年,开启科技新春新纪元

在这博主提前祝大家蛇年快乐呀!!! 随着人工智能(AI)技术的飞速发展,其影响力已经渗透到社会生活的方方面面。在中国传统节日 —— 春节期间,AI 技术也展现出了巨大的潜力,为中国年带…

WPS数据分析000007

目录 一、分列 智能分列 出生日期 数值转换 公式不运算 二、数据对比 离职员工 新入职员工 都在职的员工 三、合并计算 四、拆分表格 合并表格 一、分列 智能分列 出生日期 数据求和 文本型数字左对齐;数值型数字右对齐 数值转换 方式一: 方…

fps一些内容添加

1 增强输入要点记录 输入 :输入值的类型 布尔 1d,2d,3d 映射:就是确定按键输入键位,输入类型,和一些触发器(按键方式)修改器(对输出值进行修改) 基本的&am…

深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用

title: 深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用 date: 2025/1/26 updated: 2025/1/26 author: cmdragon excerpt: 在现代数据库管理系统中,索引技术是提高查询性能的重要手段。当数据量不断增长时,如何快速、有效地访问这些数据成为了数据库设计的核…

【反悔堆】【hard】力扣871. 最低加油次数

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。 沿途有加油站,用数组 stations 表示。其中 stations[i] [positioni, fueli] 表示第 i 个加油站位于出发位置东面 positioni 英里处,并且有 fueli 升汽油。 假设汽车油…

知识库建设对提升团队协作与创新能力的影响分析

内容概要 在当今快速变革的商业环境中,知识库建设的重要性愈发凸显。它不仅是信息存储的载体,更是推动组织内部沟通与协作的基石。通过系统整理与管理企业知识,团队成员能够便捷地访问相关信息,使得协作过程更为流畅,…

SpringBoot-Vue整合百度地图

文章目录 一、Spring Boot整合百度地图的步骤1. 申请百度地图的AK值2. 创建实体类3. 创建Controller层4. 前端集成百度地图4.1 在Vue项目中安装百度地图Vue组件库4.2 在Vue项目中引入百度地图API4.3 创建地图组件 二、实现功能说明1. 前端部分:2. 后端部分&#xff…

【Docker】快速部署 Nacos 注册中心

【Docker】快速部署 Nacos 注册中心 引言 Nacos 注册中心是一个用于服务发现和配置管理的开源项目。提供了动态服务发现、服务健康检查、动态配置管理和服务管理等功能,帮助开发者更轻松地构建微服务架构。 步骤 拉取镜像 docker pull nacos/nacos-server启动容器…

RAG技术:通过向量检索增强模型理解与生成能力

网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…

Java设计模式:行为型模式→策略模式

Java 策略模式详解 1. 定义 策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将每一个算法封装起来,并使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。通过这种模式&#xf…

linux通过deb包安装(命令模式)

通过下载deb包安装Chrome浏览器 - lyy19s Wikihttps://lyy1119.github.io/%E8%BD%AF%E4%BB%B6%E4%BD%BF%E7%94%A8/Linux/InstallChrome/

C基础寒假练习(4)

输入带空格的字符串&#xff0c;求单词个数、 #include <stdio.h> // 计算字符串长度的函数 size_t my_strlen(const char *str) {size_t len 0;while (str[len] ! \0) {len;}return len; }int main() {char str[100];printf("请输入一个字符串: ");fgets(…

Android View 的事件分发机制解析

前言&#xff1a;当一个事件发生时&#xff08;例如触摸屏幕&#xff09;&#xff0c;事件会从根View&#xff08;通常是Activity的布局中的最顶层View&#xff09;开始&#xff0c;通过一个特定的路径传递到具体的View&#xff0c;这个过程涉及到三个关键的阶段&#xff1a;事…

WPS数据分析000005

目录 一、数据录入技巧 二、一维表 三、填充柄 向下自动填充 自动填充选项 日期填充 星期自定义 自定义序列 1-10000序列 四、智能填充 五、数据有效性 出错警告 输入信息 下拉列表 六、记录单 七、导入数据 ​编辑 八、查找录入 会员功能 Xlookup函数 VL…

【Spring】Spring启示录

目录 前言 一、示例程序 二、OCP开闭原则 三、依赖倒置原则DIP 四、控制反转IOC 总结 前言 在软件开发的世界里&#xff0c;随着项目的增长和需求的变化&#xff0c;如何保持代码的灵活性、可维护性和扩展性成为了每个开发者必须面对的问题。传统的面向过程或基于类的设计…