15分钟学 Go 第 56 天:架构设计基本原则

第56天:架构设计基本原则

学习目标

理解和掌握基本的架构设计原则,以提升软件系统的可维护性、可扩展性和可重用性。

内容提纲

  1. 架构设计原则概述
  2. 常见架构设计原则
    • 单一职责原则 (SRP)
    • 开放/封闭原则 (OCP)
    • 里氏替换原则 (LSP)
    • 接口分离原则 (ISP)
    • 依赖反转原则 (DIP)
  3. 架构设计的最佳实践
  4. 示例代码
  5. 运行流程图
  6. 总结

1. 架构设计原则概述

架构设计原则是开发软件系统时用以指导设计和开发过程的基本准则。这些原则帮助开发者创建更优秀的软件架构,从而确保可维护性、可扩展性、可重用性和良好的性能。

2. 常见架构设计原则

2.1 单一职责原则 (SRP)

定义:一个类应该只有一个原因引起它的变化。换句话说,每个类应该专注于完成一项职责。

示例代码

package mainimport "fmt"// 用户管理类
type User struct {Name stringAge  int
}// 发送邮件功能
type EmailService struct{}func (es *EmailService) SendEmail(email string) {fmt.Printf("Sending email to %s\n", email)
}// 用户服务
type UserService struct {emailService *EmailService
}func (us *UserService) CreateUser(name string, age int, email string) {user := User{Name: name, Age: age}fmt.Printf("User created: %+v\n", user)us.emailService.SendEmail(email)
}func main() {emailService := &EmailService{}userService := &UserService{emailService: emailService}userService.CreateUser("Alice", 30, "alice@example.com")
}

运行流程图

+---------------------+
|  创建 UserService   |
|  +----------------+  |
|  | EmailService   |  |
|  +----------------+  |
+---------------------+|+---------------------+|  CreateUser        |+---------------------+|+---------------------+|  发送邮件          |+---------------------+

2.2 开放/封闭原则 (OCP)

定义:软件实体(类、模块、函数等)应当对扩展开放,对修改封闭。即,应该可以通过添加新功能或新代码来扩展系统,而不需要去修改现有的代码。

示例代码

package mainimport "fmt"// Shape 接口
type Shape interface {Area() float64
}// 矩形
type Rectangle struct {Width, Height float64
}func (r Rectangle) Area() float64 {return r.Width * r.Height
}// 圆
type Circle struct {Radius float64
}func (c Circle) Area() float64 {return 3.14 * c.Radius * c.Radius
}// 计算总面积
func TotalArea(shapes []Shape) float64 {total := 0.0for _, shape := range shapes {total += shape.Area()}return total
}func main() {shapes := []Shape{Rectangle{Width: 10, Height: 5},Circle{Radius: 7},}fmt.Printf("Total Area: %.2f\n", TotalArea(shapes))
}

运行流程图

+---------------------+
|   TotalArea        |
+---------------------+|
+----------+----------+
|                     |
|                     |
+                     +
|                     |
+--------+------------+
|  计算每个 Area     |
+---------------------+

2.3 里氏替换原则 (LSP)

定义:子类对象能够替换父类对象,并且在程序运行中不会影响程序的正常运行。

示例代码

package mainimport "fmt"// Bird 接口
type Bird interface {Fly() string
}// Sparrow 是 Bird 的实现
type Sparrow struct{}func (s Sparrow) Fly() string {return "Sparrow flying"
}// Ostrich 是 Bird 的实现,但不能飞
type Ostrich struct{}func (o Ostrich) Fly() string {return "Ostrich can't fly"
}// 使用 Bird 接口
func MakeBirdFly(bird Bird) {fmt.Println(bird.Fly())
}func main() {sparrow := Sparrow{}ostrich := Ostrich{}MakeBirdFly(sparrow) // 输出: Sparrow flyingMakeBirdFly(ostrich) // 输出: Ostrich can't fly
}

运行流程图

+---------------------+
|   MakeBirdFly      |
+---------------------+|
+----------+----------+
|                     |
|                     |
+                     +
|                     |
+--------+------------+
|  调用 Fly 方法     |
+---------------------+

2.4 接口分离原则 (ISP)

定义:客户端不应该被迫依赖于它不使用的方法。即接口应该尽可能的细小,客户端只需关注自身需要的方法。

示例代码

package mainimport "fmt"// 形状接口
type Shape interface {Area() float64
}// 3D 形状接口
type ThreeDimensionalShape interface {ShapeVolume() float64
}// 矩形
type Rectangle struct {Width, Height float64
}func (r Rectangle) Area() float64 {return r.Width * r.Height
}// 立方体
type Cube struct {Side float64
}func (c Cube) Area() float64 {return 6 * (c.Side * c.Side)
}func (c Cube) Volume() float64 {return c.Side * c.Side * c.Side
}func main() {var shapes []Shapeshapes = append(shapes, Rectangle{Width: 10, Height: 5})for _, shape := range shapes {fmt.Printf("Area: %.2f\n", shape.Area())}cube := Cube{Side: 3}fmt.Printf("Cube Area: %.2f, Volume: %.2f\n", cube.Area(), cube.Volume())
}

运行流程图

+---------------------+
|  计算形状面积      |
+---------------------+|
+----------+----------+
|                     |
|                     |
+                     +
|                     |
+--------+------------+
|  计算立方体体积    |
+---------------------+

2.5 依赖反转原则 (DIP)

定义:高层模块不应依赖于低层模块,二者应依赖于抽象(接口)。抽象不应依赖于细节,细节应依赖于抽象。

示例代码

package mainimport "fmt"// 数据库接口
type Database interface {Query() string
}// MySQL 数据库实现
type MySQL struct{}func (m MySQL) Query() string {return "Query from MySQL"
}// PostgreSQL 数据库实现
type PostgreSQL struct{}func (p PostgreSQL) Query() string {return "Query from PostgreSQL"
}// 数据库服务
type DatabaseService struct {db Database
}func (ds *DatabaseService) Execute() {fmt.Println(ds.db.Query())
}func main() {mysqlService := &DatabaseService{db: MySQL{}}mysqlService.Execute()  // 输出: Query from MySQLpostgresService := &DatabaseService{db: PostgreSQL{}}postgresService.Execute() // 输出: Query from PostgreSQL
}

运行流程图

+---------------------+
|  DatabaseService    |
+---------------------+|
+----------+----------+
|                     |
|                     |
+                     +
|                     |
+-------+-------------+
|  执行 Query 方法    |
+---------------------+

3. 架构设计的最佳实践

  • 模块化设计:将代码分为多个模块,每个模块负责特定功能,这提升了可读性和可维护性。
  • 高内聚低耦合:模块内部结构应保持高度一致性,而不同模块之间应保持低耦合,以便于代码的修改和重用。
  • 使用设计模式:设计模式有助于解决特定的架构问题,提升代码质量。
  • 自动化测试:通过单元测试和集成测试确保代码质量和系统可靠性。
  • 持续重构:在开发过程中保持代码质量,定期重构代码以适应新需求。

4. 示例代码的整体运行

以上代码展示了各种设计原则的实现方式。进行这些示例时,您可以在 Go 环境中逐一运行这些代码,并观察输出结果,帮助理解每个原则的应用。

代码的运行流程图展示了每个主要方法的调用路径,以及如何通过不同模块进行交互,体现了架构设计原则的有效性。

5. 运行流程图总结

每个示例中的运行流程图清晰地展示了不同组件之间的交互关系,帮助开发者理解各个设计原则如何有效整合,从而构成一个良好的软件架构。

6. 总结

熟练掌握架构设计原则是软件开发过程中的关键因素。这些原则不仅能够提升软件的质量和可维护性,同时也提高了团队的开发效率。通过实际案例的学习与实践,可以更好地理解和应用这些原则,为构建高质量的系统打下坚实的基础。


怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

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

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

相关文章

【B+树特点】

B树的特点 B树是B树的一种变体,广泛用于数据库系统和文件系统中,特别是在索引结构中。B树在B树的基础上进行了优化,主要在数据存储和查询效率上有所提升。以下是B树的主要特点: 1. 所有数据存储在叶子节点 与B树不同&#xff0…

高翔【自动驾驶与机器人中的SLAM技术】学习笔记(十三)图优化SLAM的本质

一、直白解释slam与图优化的结合 我从b站上学习理解的这个概念。 视频的大概位置是1个小时以后,在第75min到80min之间。图优化SLAM是怎么一回事。 slam本身是有运动方程的,也就是运动状态递推方程,也就是预测过程。通过t1时刻&#xff0c…

PyCharm2024.2.4安装

一、官网下载 1.从下面的链接点进去 PyCharm: The Python IDE for data science and web development by JetBrains 2.进入官网后,下载pycharm安装包 3.点击下载能适配你系统的安装包 4.安装包下载完成 二、安装 1.下载完成后,打开点击右键&#xff…

WebSocket简易聊天室实现(有详细解释)

完整代码 Arata08/online-chat-demo 服务端: 1.编写配置类,扫描有 ServerEndpoint 注解的 Bean import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.s…

Vue 3 中的原生事件监听与组件事件处理详解

Vue 3 中的原生事件监听与组件事件处理完全指南 在 Vue 3 中,事件监听和事件处理是组件交互中的关键部分。Vue 提供了一套简单而强大的事件处理机制,可以方便地监听 DOM 原生事件和组件自定义事件。本篇文章将详细介绍 Vue 3 中事件的使用,包…

解决Xeyes: Error can‘t open display,远程X无法连通问题。

一、问题分析 提前申明: 本次实验使用REHL 8 进行操作! 客户机 A 为X-Client ,即远程X的客户端。 服务机 B 为X-Server,即远程X的服务端。 问题的所有操作均在已经配置好Xorg的前提下进行的,不知道不配置会有什么影响&…

19.UE5道具掉落

2-21 道具掉落,回血、回蓝、升级提升伤害_哔哩哔哩_bilibili 目录 1.道具的创建,道具功能的实现 2.随机掉落 1.道具的创建,道具功能的实现 新建Actor蓝图,并命名为道具总类,添加一个Niagara粒子组件和一个碰撞箱bo…

Java 语言的强大特性

一、面向对象 面向对象编程(OOP)是一种编程范式,Java 完全遵循这一范式,并具备封装、继承和多态三大核心特性。 1. 封装 封装是将数据和操作封装在类中,通过访问修饰符(如 public、private、protected&am…

DevExpress WinForms中文教程:Data Grid - 如何绑定到实体框架数据源?

在本教程中,您将学习如何将DevExpress WinForms的网格控件绑定到实体框架数据源、如何使用数据注释属性来更改网格显示和管理数据的方式,以及如何将单元格值更改发送回数据源。 P.S:DevExpress WinForms拥有180组件和UI库,能为Wi…

PostgreSQL学习总结(13)—— PostgreSQL 15.8 如何成就数据库性能王者?

前言 在当今数据驱动的时代,数据库的性能无疑是企业和开发者最为关注的焦点之一。而 PostgreSQL 15.8 的横空出世,犹如一颗璀璨的明星,在数据库性能的苍穹中闪耀着耀眼的光芒,引得无数人为之侧目。今天,就让我们一同揭…

树形dp总结

这类题型在 dp 中很常见,于是做一个总结吧!!! 最经典的题:没有上司的舞会 传送门:没有上司的舞会 - 洛谷 状态表示: dp[i][0] 为 以 i 为根的子树中,选择 i 节点的最大欢乐值 d…

关于强化学习的一份介绍

在这篇文章中,我将介绍与强化学习有关的一些东西,具体包括相关概念、k-摇臂机、强化学习的种类等。 一、基本概念 所谓强化学习就是去学习:做什么才能使得数值化的收益信号最大化。学习者不会被告知应该采取什么动作,而是必须通…

微服务day07

MQ高级 发送者可靠性,MQ的可靠性,消费者可靠性。 发送者可靠性 发送者重连 连接重试的配置文件: spring:rabbitmq:connection-timeout: 1s # 设置MQ的连接超时时间template:retry:enabled: true # 开启超时重试机制initial-interval: 10…

i春秋-EXEC(命令执行、nc传输文件、带外通道传输数据)

练习平台地址 竞赛中心 题目描述 题目内容 小猫旁边有一个no sign F12检查页面 没有提示 检查源代码 发现使用了vim编辑器 进而联想到vim编辑器的临时交换文件.xxx.swp 访问.index.php.swp&#xff0c;成功下载文件 使用vim -r 查看文件内容 vim -r index.php.swp <?p…

【C语言】前端未来

你对前端未来的技术趋势有何看法&#xff1f;例如WebAssembly、WebXR、PWA等。 对未来前端技术趋势的看法&#xff0c;我认为有几个关键方向正在快速发展&#xff1a; WebAssembly (WASM)&#xff1a;随着性能需求的增长&#xff0c;WebAssembly作为一种低级字节码运行环境&…

【Web前端】Promise的使用

Promise是异步编程的核心概念之一。代表一个可能尚未完成的操作&#xff0c;并提供了一种机制来处理该操作最终的成功或失败。具体来说&#xff0c;Promise是由异步函数返回的对象&#xff0c;能够指示该操作当前所处的状态。 当Promise被创建时&#xff0c;它会处于“待定”&a…

YOLO系列基础(六)YOLOv1原理详解,清晰明了!

系列文章地址 YOLO系列基础&#xff08;一&#xff09;卷积神经网络原理详解与基础层级结构说明-CSDN博客 YOLO系列基础&#xff08;二&#xff09;Bottleneck瓶颈层原理详解-CSDN博客 YOLO系列基础&#xff08;三&#xff09;从ResNet残差网络到C3层-CSDN博客 YOLO系列基础…

硬石电机学习2024116

F4 概况 共模抑制线圈作用是滤波 LD3.3是将5v转为芯片用的3.3V CH340用于板子和电脑通讯 光耦隔离保护主控 16M的外部flash 1M的芯片内部的flash 10kHZ高速的光耦隔离&#xff0c;1M的低俗光耦隔离 F4 stm32概况 stm8和51都是一次可以运算处理8位的 32表示一次处理32位…

[Qt] Qt删除文本文件中的某一行

需求 我们经常读一个文件或者直接往一个空白文件中写文本&#xff0c;那么该如何使用Qt在一个文本文件中删除某一行 代码 #include <QCoreApplication> #include <QIODevice> #include <QFile> #include <QTextStream> #include <QString> #i…

【OceanBase 诊断调优】—— ocp上针对OB租户CPU消耗计算逻辑

指标介绍 租户 CPU 使用量 * 100 / 租户 CPU 分配量。 指标参数说明 指标项指标名称单位租户 CPU 消耗ob_tenant_cpu_percent% 计算表达式 sum(rate(ob_sysstat{stat_id"140013",LABELS}[INTERVAL])) by (GBLABELS) / sum(ob_sysstat{stat_id"140005"…