设计原则及设计模式基础

news2024/11/24 20:52:35

 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的代码设计经验的总结,使用设计模式是为了可以重用代码,让代码更容易被他人理解并且提高代码的可靠性。

1 设计模式概述

GoF(Gang Of Four 四人组,指4位著名软件工程学者),在1994年归纳发表了23中在软件开发中使用频率较高的设计模式。

类型

数量

设计模式

职责

创建型

5

单例模式

描述如何创建对象。

工厂方法模式

抽象工厂模式

原型模式

建造者模式

结构型

7

适配器模式

描述如何实现类或对象的组合。

桥接模式

组合模式

装饰模式

外观模式

享元模式

代理模式

行为型

11

职责链模式

描述类或对象怎样交互以及怎样分配职责

命令模式

解释器模式

迭代器模式

中介者模式

备忘录模式

观察者模式

状态模式

策略模式

模板方法模式

访问者模式

表 GoF 23中设计模式

1.1 设计模式掌握点

1)设计模式的意图,解决的问题,使用场景;

2)如何解决问题,其结构图,关键代码;

3)至少两个应用实例,1个生活中,1个软件中;

4)优缺点,使用时注意事项;

2 UML

UML(Unified Modeling Language,统一建模语言)是最常用、使用最广泛的图形描述技术。

2.1 关联

是类与类之间最常用的一种关系,用于表示一类对象与另一类对象之间有联系。在UML中,关联关系通常又包含如下几种形式:

1) 双向关联

默认情况下,关联是双向的,用实线连接两个类,表示它们的双向关联。例如,用户创建订单,得到一个新订单,而订单则与这个用户相关联。

图 用户与订单双向关联

2) 单向关联

用带箭头的实线表示单向关联,其中箭头指向被关联的元素。例如,用户拥有手机。

图 用户单向关联手机

3)自关联

类的属性对象类型是该类的本身。例如,节点Node类包含属性:nextNode表示下一节点。

图 Node的自关联

4) 多重性关联

又称为重数性关联关系,表示两个关联对象在数量上的对于关系,比如用户与订单 1对多的关联关系。

图 用户与订单1对N的关联关系

5) 聚合关系

表示整体与部分的关系。在聚合关系中,成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在。在UML中,用空心菱形及带箭头(也可以不带箭头)的直线表示。空心菱形指向整体,箭头指向成员对象。例如,图书馆和书籍是聚合关系。

图 图书馆与书籍的聚合关系

组合关系

表示整体与部分的关系,在组合关系中,整体对象可以控制成员对象的生命周期,一旦整体对象不存在,成员对象也将不存在。在UML中,用实心菱形及带箭头(也可以不带箭头)的直线表示。实心菱形指向整体,箭头指向成员对象。例如,人与嘴巴是组合关系。

图 人和嘴巴的组合关系

2.2 依赖关系

是一种使用关系,特定事务的改变有可能会影响到使用该事务的其他事务。在大多数情况下,依赖关系体现在某个类的方法使用另一个类的对象作为参数。在UML中,依赖关系用带箭头的虚线表示,箭头指向被依赖的元素。

例如,人看书。People有个read方法,参数为Book类型,因此,People依赖Book。

图 人与书的依赖关系

3 设计原则

面向对象设计原则是为支持可维护性复用而诞生,是从许多设计方案中总结出的指导性原则。也是用于评价一个设计模式的的使用效果的重要指标之一。

最常用的有7种设计原则。

单一职责原则

一个类只负责一个功能领域中的相应职责。

开闭原则

软件实体应对扩展开放,而对修改关闭。

里氏代换原则

所有引用基类对象的地方能够透明地使用其子类的对象。

依赖倒转原则

抽象不应该依赖于细节,细节应该依赖于抽象。

接口隔离原则

使用多个专门的接口,而不使用单一的总接口。

合成复用原则

尽量使用对象组合,而不是继承来达到复用的目的。

迪米特法则

一个软件实体应当尽可能少地与其他实体发生相互左右。

表 7种常用的面向对象设计原则

3.1 单一职责原则

一个类只负责一个功能领域中的相应职责。或者说,就一个类而言,应该只有一个引起它变化的原因。

例如,创业初期,老板要身兼多职,既要去跑业务、也要管理财务,生意有起色的话,还要去招聘。

图 创业初期的公司

在付出了99%的努力后,生意没有起色,快要倒闭的时候,靠着1%的机遇,让公司存活了下去,并且开始做大做强。这个时候,Boss就不能身兼多职了,要放权,让员工各司其职,专业的人做专业的事。否则,公司是绝对做不大的。

图 做大做强的公司

3.2 开闭原则

是最重要的对象设计原则。一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

对于软件项目,会随着时间的推移,对应的需求也会发生变化,当面临新的需求时,应尽量保证系统的设计框架是稳定的。

图 历经千年的“镇海吼”

历经千年不倒的“镇海吼”,在经过专家们的多次摧残式的修复后,变得更加伤痕累累,加大了倒塌的可能性。

为了满足开闭原则,需要对系统进行抽象化设计,这是开闭原则的关键。

3.3 里氏代换原则

所有引用基类的地方必须能透明地使用其子类的对象。是实现开闭原则的重要方式之一。

在运用里氏代换原则时,应该将父类设计为抽象类或者接口,在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型。

例如,有一家汽车销售店,其出售奥迪及保时捷品牌的车。后续可能会销售其他品牌车。

图 汽车销售店UML图

上图设计氏不符合开闭原则的。当增加新的品牌时,需要新增一个方法。需要修改CarShop的代码。根据里氏代换原则,重新设计为:

图 优化后的汽车销售店UML图

3.4 依赖倒转原则

抽象不应该依赖于细节,细节应该依赖于抽象。要针对接口编程,而不是针对实现编程。

面向对象

以对象为单位,考虑它的属性及方法。

面向过程

以一个具体的流程(事务过程)为单位,考虑它的实现。

面前接口

是针对复用技术而言,与上面两个面向不是同一个问题。

表 面向接口与面向对象、面向过程的区别

例如,将大象放入冰箱,我们针对的是大象这个种类,考虑的是怎么把大象怎么放进冰箱。而面对接口编程,则考虑的是把物品(包括动物)放入冰箱。

图 面向接口的“将大象放入冰箱”问题

3.5 接口隔离原则

使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些它不需要的接口。

在使用接口时,要注意颗粒度问题,颗粒度太细的话,容易造成接口的泛滥,太粗则可能会不符合接口隔离原则。

3.6 合成复用原则

尽量使用对象组合,而不是继承来达到复用的目的。

通过继承来进行复用的主要问题在于继承复用会破坏系统的封装性。因为继承会将基类的实现细节暴露给子类,如果基类发生改变,那么子类的实现也不得不发生改变,没有足够的灵活性。

例如,手机由屏幕、芯片及电池组成,苹果公司几乎每一年都会推出新的一款手机。

图 通过继承来实现手机生产

假如Foxconn的makeIPhone方法在添加个参数camera,那么其子类也同时需要修改。现在我们根据合成复用原则,做优化:

图 通过组合来实现手机生产

3.7 迪米特法则

一个软件实体应当尽可能少地与其他实体发生相互作用。

迪米特法则还要另一种定义形式:不要和“陌生人”说话,只与你的之间朋友通信等。“朋友”包括以下几类:

  1. 当前对象本身;
  2. 以参数形式传入到当前对象方法中的对象;
  3. 当前对象的成员对象,如果当前对象成员对象是一个集合,那么集合中的元素也是朋友;
  4. 当前对象所创建的对象。

迪米特法则要求在设计系统时,应该尽量减少对象之间的交互。如果两个对象之间不必彼此通信,那么这两个对象就不应当发生任何直接的相互作用;如果其中一个对象需要调用另一个对象的方法,可以通过第三者转发这个调用(引入一个合理的第三者来降低现有对象之间的耦合度)。

例如,每个服装公司都有自己的网站用来给客户下单。

图 客户在服装公司官网上下单

客户与服装公司的耦合度是很高的,受限于公司网站是否有效、付款规则等。假如某些服装公司下单规则改变时,Customer需要做相应的修改。

我们引入第三方交易平台来降低客户与服装公司的耦合度。

图 引入第三方平台后,客户之间在第三方平台下单

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

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

相关文章

ubuntu安装单个redis服务

1.apt-get install redis-server 使用lighthouse用户这样操作会报与权限有关的错误, 改成使用root账号操作 2.安装完成后,Redis服务器会自动启动,查看进程是否正常启动 ps -axu|grep redis redis 18689 0.1 0.4 40136 6860 ? …

第3讲 Camera Sensor 数据流

Camera Sensor Block Camera Sensor Output Format raw8 一个像素点用8bit来表示,范围0~256 raw10 一个像素点用10bit来表示,范围0~1024 raw12 一个像素点用12bit来表示,范围0~4096 Camera Sensor Fr…

智慧园区:如何利用AI识别与视频技术实现工业园区监管模式的升级?

一、背景分析 智慧园区建设的目标是通过运用现代信息技术,通过智能化管理,解决园区管理中存在的许多难题,例如信息不对称、资源浪费等问题,将园区内的设施、设备和系统进行连接和互通,园区可以实现各种资源的高效利用…

这一次,Python 真的有望告别 GIL 锁了?

Python 中有一把著名的锁——全局解释器锁(Global Interpreter Lock,简写 GIL),它的作用是防止多个本地线程同时执行 Python 字节码,这会导致 Python 无法实现真正的多线程执行。(注:本文中 Pyt…

TexSpire-比markdown更为简洁的文本标记语言,用文字即可生成演示效果

文章目录 一、前言二、语言特点三、举例1、文本框2、表格3、折线图4、思维导图 四、相关资料 一、前言 老实说,本人对于ppt的花里胡哨深恶痛绝,特别是每一次汇报,都需要花费我很多时间去找模板,去设计,去美化内容时&a…

【源码分析系列】number-precision和bignumber.js

01_JS精度 好久前在公司分享的文章,现在才发…本文阐述了为什么0.1 0.2 ! 0.3,并分析了number-precision和bignumber.js的解决原理 被JS精度问题小坑了一把,所以系统来 复习 学习一波~ 背景 在实际业务开发中,可能会遇到一下问题…

Redis_简介(1)

目录 Redis简介 Redis特性 Redis 优势 Redis应用场景 源码等资料获取方法 Redis简介 Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由…

Git命令-状态与版本查看

Git是一个强大的分布式管理系统,版本控制主要在本地端完成,在团队合作和协助开发中,都在广泛使用Git工具,因为他免费哈哈哈 目录 git status git reflog git reset --hard 版本号 git status 可以查看当前git状态 On branch master 是你当前的分支状态,当前我是在master主…

[分布式] zookeeper集群与kafka集群

目录 一、Zookeeper 概述1.1 Zookeeper定义1.2 Zookeeper 工作机制1.3 Zookeeper 特点1.4 Zookeeper 数据结构1.5 Zookeeper 应用场景1.6 Zookeeper 选举机制 二、 部署 Zookeeper 集群2.1 环境部署2.2 关闭防火墙2.3 安装 JDK 下载安装包 安装 Zookeeper2.4 修改配置文件2.5 将…

[NGINX] NGINX下载、安装编译、启动检查停止命令

一、NGINX 下载 mkdir -p /soft/nginx cd /soft/nginx wget https://nginx.org/download/nginx-1.21.6.tar.gz二、下载相关依赖 ①在线安装依赖: yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel ②下载依赖到本地安装依赖: y…

2023年7月23日 星期三 Linux驱动作业

1.使用驱动代码实现如下要求 a.应用程序通过阻塞的io模型来读取number变量的值 b.number是内核驱动中的一个变量 c.number的值随着按键按下而改变(按键中断) 例如number0 按下按键number1再次按下按键number0 d.在按下按键的时候需要同时将1ed1的状态取反 e.驱动中需要编写字符…

FlinkCDC第四部分-同步mysql到mysql,ctrl就完事~(flink版本1.17.1)

本文介绍了不同源单表-单表同步,不同源多表-单表同步。 注:此版本支持火焰图 Flink版本:1.17.1 环境:Linux CentOS 7.0、jdk1.8 基础文件: flink-1.17.1-bin-scala_2.12.tgz、 flink-connector-jdbc-3.0.0-1.16.…

LeetCode·每日一题·2544. 交替数字和·模拟

作者:小迅 链接:https://leetcode.cn/problems/alternating-digit-sum/solutions/2341276/mo-ni-zhu-shi-chao-ji-xiang-xi-by-xun-ge-7fjq/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权&#…

产品经理学习画原型(三)

1.布尔运算的使用 合并必须选择两个及以上元件 合并后: 组合: 去除顶层:

【基于FPGA的芯片设计】32位RISC-V存储器

实验板卡:xc7a100tlc sg324-2L,共20个开关 实验要求

述往思来,砥砺前行—易我文化系列课《企业发展历程》讲座圆满举行

2023年6月9日,易我文化系列课《企业发展历程》讲座如期举行并取得圆满成功。 此次讲座邀请了易我客服总监——喻涛为大家授课,旨在让员工对易我的历史、发展以及未来有更全面的认识,引导员工从易我发展史中汲取奋进力量,增强集体…

【kubernetes系列】Kubernetes之ServiceAccount

概述 Service Account是什么呢,顾名思义,服务账号,一种给服务使用的账号,它不是给Kubernetes的集群的用户(系统管理员、运维人员、租户用户等)使用,而是给运行在Pod里的进程用的,它…

【雕爷学编程】Arduino动手做(113)---5110液晶屏模块2

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&am…

基于springboot+Redis的前后端分离项目(八)-【黑马点评】

🎁🎁资源文件分享 链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA?pwdeh11 提取码:eh11 好友关注&Feed流 (一)好友关注-关注和取消关注(二)好友关注-共同关注(三) 好友…

飞行动力学 - 第7节-part1-起飞性能 之 基础点摘要

飞行动力学 - 第7节-part1-起飞性能 之 基础点摘要 1. 气动特性2. 起飞性能3. 性能指标3.1 地面滑跑阶段3.2 起飞滑跑距离估算 4. 跑道4.1 编号4.2 等级 5. 参考资料 1. 气动特性 起飞不仅需要考虑升力,还需要在有限跑道长度上加速,因此襟翼放出的角度不…