设计模式B站学习(一)(java)

news2024/11/29 12:47:45

这里写目录标题

  • 一、设计模式概述
    • 1.1 软件设计模式的产生背景
    • 1.2 软件设计模式的概念
    • 1.3 学习设计模式的必要性
    • 1.4 设计模式分类
  • 二、UML图
    • 2.1 类图概述
    • 2.2 类图的作用
    • 2.3 类图表示法
      • 2.3.1 类图表示方法
      • 2.3.2 类与类之间关系的表示方法
        • 2.3.2.1 关联关系
        • 2.3.2.2 聚合关系
        • 2.3.2.3 组合关系
        • 2.3.2.4 依赖关系
        • 2.3.2.5 继承关系
        • 2.3.2.6 实现关系
  • 三、软件设计原则
    • 3.1、开闭原则(Open Closed Principle)
    • 3.2、里氏替换原则(Liskov Substitution Principle)
    • 3.3、依赖倒置原则(Dependence Inversion Principle)
    • 3.4、接口隔离原则(Interface Segregation Principle)
    • 3.5、迪米特法则(最少知道原则)(Law of Demeter)
    • 3.6、合成复用原则(Composite Reuse Principle)合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

一、设计模式概述

1.1 软件设计模式的产生背景

"设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中。

​ 1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫·亚历山大(Christopher Alexander)在他的著作《建筑模式语言:城镇、建筑、构造》中描述了一些常见的建筑设计问题,并提出了 253 种关于对城镇、邻里、住宅、花园和房间等进行设计的基本模式。

​ 1990年软件工程界开始研讨设计模式的话题,后来召开了多次关于设计模式的研讨会。直到1995 年,艾瑞克·伽马(ErichGamma)、理査德·海尔姆(Richard Helm)、拉尔夫·约翰森(Ralph Johnson)、约翰·威利斯迪斯(John Vlissides)等 4 位作者合作出版了《设计模式:可复用面向对象软件的基础》一书,在此书中收录了 23 个设计模式,这是设计模式领域里程碑的事件,导致了软件设计模式的突破。这 4 位作者在软件开发领域里也以他们的“四人组”(Gang of Four,GoF)著称。

1.2 软件设计模式的概念

软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。

1.3 学习设计模式的必要性

设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。

正确使用设计模式具有以下优点。

可以提高程序员的思维能力、编程能力和设计能力。
使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。

1.4 设计模式分类

  1. 创建型模式

用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF(四人组)书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。

  1. 结构型模式

用于描述如何将类或对象按某种布局组成更大的结构,GoF(四人组)书中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。

  1. 行为型模式

用于描述类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,以及怎样分配职责。GoF(四人组)书中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

二、UML图

统一建模语言(Unified Modeling Language,UML)是用来设计软件的可视化建模语言。它的特点是简单、统一、图形化、能表达软件设计中的动态与静态信息。

UML 从目标系统的不同角度出发,定义了用例图、类图、对象图、状态图、活动图、时序图、协作图、构件图、部署图等 9 种图。

2.1 类图概述

类图(Class diagram)是显示了模型的静态结构,特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。类图不显示暂时性的信息。类图是面向对象建模的主要组成部分。

2.2 类图的作用

在软件工程中,类图是一种静态的结构图,描述了系统的类的集合,类的属性和类之间的关系,可以简化了人们对系统的理解;
类图是系统分析和设计阶段的重要产物,是系统编码和测试的重要模型。

2.3 类图表示法

2.3.1 类图表示方法

在UML类图中,类使用包含类名、属性(field) 和方法(method) 且带有分割线的矩形来表示,比如下图表示一个Employee类,它包含name,age和address这3个属性,以及work()方法。
在这里插入图片描述
属性/方法名称前加的加号和减号表示了这个属性/方法的可见性,UML类图中表示可见性的符号有三种:

+:表示public

-:表示private

#:表示protected

属性的完整表示方式是: 可见性 名称 :类型 [ = 缺省值]

方法的完整表示方式是: 可见性 名称(参数列表) [ : 返回类型]

注意:

  1. 中括号中的内容表示是可选的
  2. 也有将类型放在变量名前面,返回值类型放在方法名前面

在这里插入图片描述
上图Demo类定义了三个方法:

method()方法:修饰符为public,没有参数,没有返回值。
method1()方法:修饰符为private,没有参数,返回值类型为String。
method2()方法:修饰符为protected,接收两个参数,第一个参数类型为int,第二个参数类型为String,返回值类型是int。

2.3.2 类与类之间关系的表示方法

2.3.2.1 关联关系

关联关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟、丈夫和妻子等。关联关系是类与类之间最常用的一种关系,分为一般关联关系、聚合关系和组合关系。我们先介绍一般关联。

关联又可以分为单向关联,双向关联,自关联。
1.单向关联

在这里插入图片描述
2.双向关联

在这里插入图片描述
3.自关联
在这里插入图片描述

2.3.2.2 聚合关系

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

聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。

在 UML 类图中,聚合关系可以用带空心菱形的实线来表示,菱形指向整体。下图所示是大学和教师的关系图:
在这里插入图片描述

2.3.2.3 组合关系

组合表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系。

在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。

在 UML 类图中,组合关系用带实心菱形的实线来表示,菱形指向整体。下图所示是头和嘴的关系图:
在这里插入图片描述

2.3.2.4 依赖关系

依赖关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。

在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。下图所示是司机和汽车的关系图,司机驾驶汽车:
在这里插入图片描述

2.3.2.5 继承关系

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

在 UML 类图中,泛化关系用带空心三角箭头的实线来表示,箭头从子类指向父类。在代码实现时,使用面向对象的继承机制来实现泛化关系。例如,Student 类和 Teacher 类都是 Person 类的子类,其类图如下图所示:
在这里插入图片描述

2.3.2.6 实现关系

实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。

在 UML 类图中,实现关系使用带空心三角箭头的虚线来表示,箭头从实现类指向接口。例如,汽车和船实现了交通工具,其类图如图下所示:
在这里插入图片描述

三、软件设计原则

在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。

  1. 开闭原则
  2. 里氏代换原则
  3. 依赖倒转原则
  4. 接口隔离原则
  5. 迪米特法则
  6. 合成复用原则

3.1、开闭原则(Open Closed Principle)

对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。

想要达到这样的效果,我们需要使用接口和抽象类。

因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。

下面以 搜狗输入法 的皮肤为例介绍开闭原则的应用。

【例】搜狗输入法 的皮肤设计。

分析:搜狗输入法 的皮肤是输入法背景图片、窗口颜色和声音等元素的组合。用户可以根据自己的喜爱更换自己的输入法的皮肤,也可以从网上下载新的皮肤。这些皮肤有共同的特点,可以为其定义一个抽象类(AbstractSkin),而每个具体的皮肤(DefaultSpecificSkin和HeimaSpecificSkin)是其子类。用户窗体可以根据需要选择或者增加新的主题,而不需要修改原代码,所以它是满足开闭原则的。
在这里插入图片描述

3.2、里氏替换原则(Liskov Substitution Principle)

里氏代换原则是面向对象设计的基本原则之一。

里氏代换原则:任何基类可以出现的地方,子类一定可以出现。通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

下面看一个里氏替换原则中经典的一个例子

【例】正方形不是长方形。

在数学领域里,正方形毫无疑问是长方形,它是一个长宽相等的长方形。所以,我们开发的一个与几何图形相关的软件系统,就可以顺理成章的让正方形继承自长方形。
在这里插入图片描述
代码如下:
长方形类(Rectangle):

public class Rectangle {
    private double length;
    private double width;

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }
}

正方形类(Square):

由于正方形的长和宽相同,所以在方法setLength和setWidth中,对长度和宽度都需要赋相同值。

public class Square extends Rectangle {
    
    public void setWidth(double width) {
        super.setLength(width);
        super.setWidth(width);
    }

    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }
}

类RectangleDemo是我们的软件系统中的一个组件,它有一个resize方法依赖基类Rectangle,resize方法是RectandleDemo类中的一个方法,用来实现宽度逐渐增长的效果。

public class RectangleDemo {
    
    public static void resize(Rectangle rectangle) {
        while (rectangle.getWidth() <= rectangle.getLength()) {
            rectangle.setWidth(rectangle.getWidth() + 1);
        }
    }

    //打印长方形的长和宽
    public static void printLengthAndWidth(Rectangle rectangle) {
        System.out.println(rectangle.getLength());
        System.out.println(rectangle.getWidth());
    }

    public static void main(String[] args) {
        Rectangle rectangle = new Rectangle();
        rectangle.setLength(20);
        rectangle.setWidth(10);
        resize(rectangle);
        printLengthAndWidth(rectangle);

        System.out.println("============");

        Rectangle rectangle1 = new Square();
        rectangle1.setLength(10);
        resize(rectangle1);
        printLengthAndWidth(rectangle1);
    }
}

我们运行一下这段代码就会发现,假如我们把一个普通长方形作为参数传入resize方法,就会看到长方形宽度逐渐增长的效果,当宽度大于长度,代码就会停止,这种行为的结果符合我们的预期;假如我们再把一个正方形作为参数传入resize方法后,就会看到正方形的宽度和长度都在不断增长,代码会一直运行下去,直至系统产生溢出错误。所以,普通的长方形是适合这段代码的,正方形不适合。
我们得出结论:在resize方法中,Rectangle类型的参数是不能被Square类型的参数所代替,如果进行了替换就得不到预期结果。因此,Square类和Rectangle类之间的继承关系违反了里氏代换原则,它们之间的继承关系不成立,正方形不是长方形。

如何改进呢?此时我们需要重新设计他们之间的关系。抽象出来一个四边形接口(Quadrilateral),让Rectangle类和Square类实现Quadrilateral接口

在这里插入图片描述

3.3、依赖倒置原则(Dependence Inversion Principle)

高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

3.4、接口隔离原则(Interface Segregation Principle)

客户端不应该被迫依赖于它不使用的方法;一个类对另一个类的依赖应该建立在最小的接口上。

3.5、迪米特法则(最少知道原则)(Law of Demeter)

迪米特法则又叫最少知道原则。

只和你的直接朋友交谈,不跟“陌生人”说话(Talk only to your immediate friends and not to strangers)。

其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

迪米特法则中的“朋友”是指:当前对象本身、当前对象的成员对象、当前对象所创建的对象、当前对象的方法参数等,这些对象同当前对象存在关联、聚合或组合关系,可以直接访问这些对象的方法。

3.6、合成复用原则(Composite Reuse Principle)合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

通常类的复用分为继承复用和合成复用两种。

继承复用虽然有简单和易实现的优点,但它也存在以下缺点:

  1. 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
  2. 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
  3. 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点:

  1. 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  2. 对象间的耦合度低。可以在类的成员位置声明抽象。
  3. 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

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

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

相关文章

C语言,指针详解

1. 指针是什么&#xff1f; 1. 指针是内存中一个最小单元的编号 2. 口头上的“指针”&#xff0c;指的是指针变量 #include<stdio.h>int main() {int a10;int * pa&a;// pa 是一个指针变量,用来存放 a 的地址//int ——> pa 所指向对象的类型//* 代表 pa是个指针…

【ros/ros2】ros2 humble镜像制作过程中碰到的问题记录

文章目录 序言1. 避免手动设置时区2. docker build中间某一步失败了3. sudo apt install ros-humble-desktop安装报错 E: Unable to locate package ros-humble-desktop4. 编译ros2 humnble时报错5. sudo rosdep init失败6. 下载依赖时失败&#xff1a;rosdep install --from-p…

局域网技术

共享信道的分配技术是局域网的核心技术&#xff0c;而这一技术又与网络的拓扑结构和传输介质有关。 拓扑结构&#xff1a; 1.总线型拓扑&#xff1a; 总线一种多点广播介质&#xff0c;所有的站点通过接口硬件连接到总线上。 传输介质主要是同轴电缆&#xff08;基带和宽带…

chatgpt赋能python:Python取消空格:如何优化代码和改善SEO?

Python取消空格&#xff1a;如何优化代码和改善SEO&#xff1f; 如果你是一位有10年python编程经验的工程师&#xff0c;那么你一定深刻体会到代码的质量对软件应用的重要性。而在今天&#xff0c;随着搜索引擎优化&#xff08;SEO&#xff09;的发展和对网页排名的更高要求&a…

FastBup:计算机视觉大型图像数据集分析工具

0.简介 官方github网址项目目的&#xff1a;当前大规模图像数据集一团糟&#xff0c;数据量巨大但质量堪忧&#xff0c;有时候训练集、验证集、测试集会有重复数据造成数据泄露。FastBup可以识别重复项、近似重复项、异常图像、错误标注、异常值&#xff0c;在cpu上就可以处理…

Apache Kafka - 流式处理

文章目录 概述什么是流式处理流式处理的一些概念时间状态流和表的二元性时间窗口 流式处理的设计模式单个事件处理使用本地状态多阶段处理和重分区使用外部查找——流和表的连接流与流的连接乱序的事件重新处理 概述 Kafka被广泛认为是一种强大的消息总线&#xff0c;可以可靠…

Zabbix(一)

介绍 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案。 功能组件 Server &#xff1a; Zabbix server是zabbix软件的核心组件 Zabbix agent向其报告可用性、系统完整性和统计信息 Zabbix server存储所有的配置信息、统计信息和操作信…

chatgpt赋能python:Python取出列表中的若干元素

Python取出列表中的若干元素 Python是一个功能强大且易于学习的编程语言&#xff0c;具有广泛的应用领域。在数据科学和机器学习中&#xff0c;Python是一个非常流行的语言&#xff0c;因为它具有许多用于处理数据和矩阵运算的库&#xff0c;例如NumPy和pandas。在Python的列表…

chatgpt赋能python:使用Python向微信发送信息的方法详解

使用Python向微信发送信息的方法详解 Python作为一种广泛应用于科学计算、数据处理等多个领域的编程语言&#xff0c;也可以用于自动化工作流程和自动发送微信消息等操作&#xff0c;大大提高了工作效率。如果你想在日常工作中用Python向微信群或个人发送自定义信息&#xff0…

linux网络设置

文章目录 一、查看网络配置1.查看网络接口信息——ifconfig1.1查看所有本机的网络的网络设备1.2设置网络接口参数1.3对指定的设备开启或关闭 2.查看主机名称——hostname2.1查看或临时设置当前主机名2.2永久设置主机名 3.查看路由表条目——route3.1查看当前主机路由表3.2添加路…

chatgpt赋能python:Python取消赋值:让你的代码更清晰简洁

Python取消赋值&#xff1a;让你的代码更清晰简洁 在Python编程中&#xff0c;我们经常需要使用赋值语句对变量进行赋值。但在某些情况下&#xff0c;我们也会发现需要取消赋值&#xff0c;即将已经赋过值的变量重新设为未赋值状态。这时&#xff0c;Python提供了一种特殊的语…

阿里云 Windows Server 2022 安装 Docker

阿里云Windows Server 2022 安装 Docker 文章目录 情景尝试正解 安装Docker管理工具安装Docker重启系统配置Docker系统路径配置Docker引擎(也许不用)启动Docker服务 情景 情景&#xff1a;最近一直在搞微服务&#xff0c;团队的服务器是阿里云的 Windows Server 2022&…

chatgpt赋能python:Python发展史:从诞生到井喷的开源之路

Python发展史&#xff1a;从诞生到井喷的开源之路 1. Python诞生的背景和历史 Python作为一种高级动态编程语言&#xff0c;在世界上得到了广泛应用&#xff0c;其诞生与发展也是有着自己的背景和历史的。20世纪90年代初期&#xff0c;著名的荷兰数学家Guido van Rossum开发了…

操作系统之文件管理

目录 认识文件管理 文件的逻辑结构 文件目录 文件的物理结构 文件存储空间管理 文件的基本操作 文件共享 文件保护 文件系统的全局结构 虚拟文件系统 内容摘自&#xff1a;4.1_1_初识文件管理_哔哩哔哩_bilibili 认识文件管理 文件——就是一组有意义的信息/数据集合…

chatgpt赋能python:Python可以用C语言吗?——一份详细解读

Python可以用C语言吗&#xff1f;——一份详细解读 Python和C语言是两种常见而重要的编程语言。Python被广泛应用于各种领域&#xff0c;从人工智能到数据科学&#xff0c;而C语言则是系统编程&#xff0c;操作系统和编译器方面最受欢迎的语言之一。许多人认为Python和C语言没…

pikachu靶场总结

目录 一.暴力破解 1.基于表单的暴力破解 2.验证码绕过&#xff08;on server&#xff09; 3.验证码绕过&#xff08;client&#xff09; 4.token防爆破 二.Cross-Site Scripting 1.先了解XSS 2.反射型xss&#xff08;get&#xff09; 3.反射型xss&#xff08;post&…

[SPSS] SPSS统计分析软件简介

SPSS的英文缩写来源于以下两个 ① Statistical Package for Social Science(社会科学统计软件包) ② Statistical Product and Service Solutions(统计产品与服务解决方案) SPSS是一种专业的统计分析软件。为用户提供了直观的图形化菜单界面&#xff0c;用户的数据管理和统计…

C++——多态与虚表

目录 1.多态的实现 2.虚表 2.1虚函数重写是怎么实现的 2.2多态的原理 2.3静态绑定与动态绑定 3.单继承体系中的虚函数表 ​编辑4.多继承体系中的虚函数表 5.菱形继承的虚函数表 6.菱形虚拟继承的虚函数表 1.多态的实现 在C中&#xff0c;要想实现多态&#xff0c;必…

认识elasticSearch并安装

一、介绍 定义&#xff1a;简称es&#xff0c;本质是一个开源的nosql数据库。主要用于全文检索&#xff0c;所以我们又称它为搜索引擎框架&#xff1b; 用途&#xff1a;实时数据搜索、日志采集分析 特点&#xff1a; 检索快。面对PB级的海量数据&#xff0c;用传统sql方式…

solr快速上手:配置从mysql同步数据(五)

0. 引言 上一节我们已经配置了新的索引&#xff0c;但是数据还是手动添加的&#xff0c;并没有实现自动从数据库同步&#xff0c;所以这一节&#xff0c;继续来实现从mysql同步数据到solr solr快速上手&#xff1a;solr简介及安装&#xff08;一&#xff09; solr快速上手&a…