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

设计模式7大原则与UML类图详解

设计模式7大原则与UML类图详解

引言 🌟

在这里插入图片描述

在软件工程领域,设计模式和UML(统一建模语言)是提高代码质量、增强系统可维护性的重要工具。设计模式提供了解决软件设计中常见问题的通用方案,而UML则为我们提供了一种可视化的建模语言,帮助我们清晰地表达系统结构和行为。本文将深入探讨设计模式的七大原则,并结合UML类图进行详细解析。

一、设计模式七大原则 💡

设计模式的七大原则是软件设计的基础准则,遵循这些原则可以使我们的代码更加灵活、可维护和可扩展。下面我们将逐一介绍这七大原则,并通过实例和类图进行说明。

1. 单一职责原则(Single Responsibility Principle) 🎯

定义:一个类应该只有一个引起它变化的原因。

解释:如果一个类承担了过多的职责,那么在一个职责发生变化时,可能会影响其他职责的实现,导致代码难以维护和扩展。遵循单一职责原则,可以使类更加专注,降低耦合度。

示例:假设我们有一个Book类,它既负责管理书籍的信息,又负责打印书籍的信息。

违反单一职责原则的类图

@startuml
class Book {- title: String- author: String+ setTitle(title: String): void+ setAuthor(author: String): void+ printBook(): void
}
@enduml

在这里插入图片描述

重构后遵循单一职责原则的类图

@startuml
class Book {- title: String- author: String+ setTitle(title: String): void+ setAuthor(author: String): void
}class BookPrinter {+ printBook(book: Book): void
}
@enduml

在这里插入图片描述

在这个重构中,我们将打印功能从Book类中分离出来,创建了一个新的BookPrinter类,专门负责打印书籍的信息。

2. 开放封闭原则(Open/Closed Principle) 🚪

定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。

解释:当我们需要为系统添加新的功能时,应该通过扩展已有模块来实现,而不是修改已有模块。这样可以避免对现有代码的修改,减少引入新错误的风险。

示例:假设我们有一个图表绘制系统,最初只支持绘制圆形。

违反开放封闭原则的类图

@startuml
class Shape {+ draw(): void
}class Circle {+ draw(): void
}
@enduml

在这里插入图片描述

每次添加新形状时,都需要修改Shape类或Circle类,这违反了开闭原则。

遵循开放封闭原则的类图

@startuml
interface Shape {+ draw(): void
}class Circle implements Shape {+ draw(): void
}class Square implements Shape {+ draw(): void
}
@enduml

在这里插入图片描述

通过定义一个Shape接口,我们可以轻松地添加新的形状类,而无需修改现有代码。

3. 里氏替换原则(Liskov Substitution Principle) 🔄

定义:所有引用基类的地方必须能透明地使用其子类的对象。

解释:子类应该能够替换父类并且不会影响程序的正确性。这意味着子类在继承父类时,不应修改父类的行为。

示例:假设我们有一个Rectangle类,然后创建了一个Square类继承自Rectangle

违反里氏替换原则的类图

@startuml
class Rectangle {- width: int- height: int+ setWidth(width: int): void+ setHeight(height: int): void+ area(): int
}class Square extends Rectangle {+ setWidth(width: int): void {super.setWidth(width)super.setHeight(width)}+ setHeight(height: int): void {super.setWidth(height)super.setHeight(height)}
}
@enduml

在这个例子中,Square类重写了setWidthsetHeight方法,导致无法正确计算面积,破坏了继承关系。

遵循里氏替换原则的类图

@startuml
interface Shape {+ area(): int
}class Rectangle implements Shape {- width: int- height: int+ setWidth(width: int): void+ setHeight(height: int): void+ area(): int
}class Square implements Shape {- side: int+ setSide(side: int): void+ area(): int
}
@enduml

RectangleSquare都作为Shape的实现类,各自实现自己的行为,避免了继承带来的问题。

4. 接口隔离原则(Interface Segregation Principle) 🔍

定义:客户端不应该依赖它不需要的接口。

解释:一个类对另一个类的依赖应该建立在最小的接口上。避免创建过大的接口,导致客户端依赖于它们不需要的部分。

示例:假设我们有一个Animal接口,包含了飞行和游泳的方法。

违反接口隔离原则的类图

@startuml
interface Animal {+ fly(): void+ swim(): void
}class Bird implements Animal {+ fly(): void+ swim(): void { throw UnsupportedOperationException() }
}class Fish implements Animal {+ fly(): void { throw UnsupportedOperationException() }+ swim(): void
}
@enduml

在这里插入图片描述

BirdFish都实现了flyswim方法,但实际上Fish不需要飞行功能,Bird不需要游泳功能。

遵循接口隔离原则的类图

@startuml
interface Flyable {+ fly(): void
}interface Swimmable {+ swim(): void
}class Bird implements Flyable {+ fly(): void
}class Fish implements Swimmable {+ swim(): void
}
@enduml

在这里插入图片描述

通过将接口拆分为FlyableSwimmable,让不同的类只实现它们需要的接口。

5. 依赖倒置原则(Dependency Inversion Principle) ⬇️⬆️

定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象。

解释:抽象不应该依赖于细节,细节应该依赖于抽象。这样可以降低模块之间的耦合度,提高系统的灵活性。

示例:假设我们有一个OrderService类,它直接依赖于Database类。

违反依赖倒置原则的类图

@startuml
class OrderService {- database: Database+ saveOrder(order: Order): void {database.save(order)}
}class Database {+ save(order: Order): void
}
@enduml

在这里插入图片描述
1)

OrderService直接依赖于Database,如果需要更换数据库,可能需要修改OrderService的代码。

遵循依赖倒置原则的类图

@startuml
interface DataStorage {+ save(order: Order): void
}class OrderService {- storage: DataStorage+ saveOrder(order: Order): void {storage.save(order)}
}class Database implements DataStorage {+ save(order: Order): void
}class CloudStorage implements DataStorage {+ save(order: Order): void
}
@enduml

在这里插入图片描述

通过引入DataStorage接口,OrderService依赖于抽象,而不是具体实现。

6. 迪米特法则(Law of Demeter) 👥

定义:一个对象应该对其他对象有最少的了解。

解释:一个类应该只与它的直接朋友通信,而不应该与陌生人通信。这有助于降低系统的耦合度。

示例:假设我们有一个University类,它直接调用了Department类的getProfessors方法,而Department类又调用了Professor类的getName方法。

违反迪米特法则的类图

@startuml
class University {- departments: List<Department>+ getProfessorNames(): List<String> {for (department in departments) {for (professor in department.getProfessors()) {print(professor.getName())}}}
}class Department {- professors: List<Professor>+ getProfessors(): List<Professor> {return professors}
}class Professor {- name: String+ getName(): String {return name}
}
@enduml

University类直接依赖于DepartmentProfessor类的内部实现。

遵循迪米特法则的类图

@startuml
class University {- departments: List<Department>+ getProfessorNames(): List<String> {for (department in departments) {for (name in department.getProfessorNames()) {print(name)}}}
}class Department {- professors: List<Professor>+ getProfessorNames(): List<String> {return [professor.getName() for professor in professors]}
}class Professor {- name: String+ getName(): String {return name}
}
@enduml

University类只与Department类交互,Department类负责内部细节,降低了耦合度。

7. 组合/聚合复用原则(Composition/Aggregation Reuse Principle) 🧩

定义:尽量使用组合/聚合关系,而不是继承关系来复用代码。

解释:组合/聚合关系比继承关系更加灵活,可以减少类之间的强耦合,提高系统的可维护性。

示例:假设我们有一个Engine类和一个Car类。

违反组合/聚合复用原则的类图

@startuml
class Engine {+ start(): void
}class Car extends Engine {+ drive(): void
}
@enduml

在这里插入图片描述

Car继承了Engine,如果Engine类发生变化,Car类也会受到影响。

遵循组合/聚合复用原则的类图

@startuml
class Engine {+ start(): void
}class Car {- engine: Engine+ drive(): void {engine.start()}
}
@enduml

在这里插入图片描述

Car类通过组合Engine类来实现功能,这样Car类与Engine类之间的耦合度更低,更容易扩展和维护。

二、UML类图详解 📊

UML(Unified Modeling Language)是一种用于软件系统可视化建模的标准语言。UML类图是UML中最常用的图之一,用于描述系统中的类及其之间的关系。接下来,我们将结合设计模式的七大原则,进一步了解UML类图的构成和用途。

1. UML类图的基本构成

类(Class)
UML中的类表示系统中的一个对象类型。一个类通常由三部分组成:

  • 类名(Class Name):位于类的顶部,用于标识类的名称。
  • 类的属性(Attributes):位于类的中间部分,用于描述类的特性或数据成员。格式为可见性 名称: 类型 [多重性],其中可见性包括+(公有)、-(私有)和#(保护)。
  • 类的方法(Methods):位于类的底部,用于描述类的行为或操作。格式为可见性 名称(参数列表): 返回类型 [多重性]

示例类图

@startuml
class Book {- title: String- author: String+ setTitle(title: String): void+ getTitle(): String+ setAuthor(author: String): void+ getAuthor(): String
}
@enduml

在这里插入图片描述

2. 类之间的关系

UML类图中的关系主要包括以下几种:

  • 继承(Inheritance/Generalization):表示子类继承父类的属性和方法。用带空心三角箭头的实线表示,箭头指向父类。

    @startuml
    class Animal
    class Bird
    Bird --|> Animal
    @enduml
    

    在这里插入图片描述

  • 实现(Implementation/Realization):表示类实现接口中的方法。用带空心三角箭头的虚线表示,箭头指向接口。

    @startuml
    interface Flyable
    class Bird
    Bird ..|> Flyable
    @enduml
    

    在这里插入图片描述

  • 关联(Association):表示类之间的一种长期关系。用实线表示,可以带箭头表示方向。关联可以是单向或双向的。

    @startuml
    class Student
    class Course
    Student "1" -- "many" Course : registers
    @enduml
    

在这里插入图片描述

  • 聚合(Aggregation):表示整体与部分的关系,其中部分可以独立于整体存在。用带空心菱形箭头的实线表示,菱形指向整体。

    @startuml
    class Car
    class Engine
    Car o-- Engine : has
    @enduml
    

    在这里插入图片描述

  • 组合(Composition):表示整体与部分的关系,其中部分不能独立于整体存在。用带实心菱形箭头的实线表示,菱形指向整体。

    @startuml
    class House
    class Room
    House *-- Room : contains
    @enduml
    

    在这里插入图片描述

  • 依赖(Dependency):表示一个类的变化可能会影响另一个类。用带虚线的箭头表示,箭头指向被依赖的类。

    @startuml
    class Order
    class Database
    Order ..> Database : uses
    @enduml
    

    在这里插入图片描述

3. 类图的绘制工具

目前,有许多工具可以帮助我们绘制UML类图,以下是一些常用的工具:

  • PlantUML:一种开源的、基于文本的UML绘图工具,支持多种格式输出。
  • StarUML:一款功能强大、界面友好的UML建模工具,支持多种UML图。
  • Visual Paradigm:一款综合性的建模工具,涵盖从需求分析到部署的各个环节。
  • Lucidchart:在线UML绘图工具,支持协作和多种格式导出。

在本博客中,我们将使用PlantUML进行类图的绘制和展示。

4. 类图在软件设计中的应用

UML类图在软件设计中有以下几个主要应用:

  • 系统分析:在设计初期,通过类图描述系统的基本结构和类之间的关系,有助于明确系统的架构。
  • 代码生成:一些工具可以根据类图自动生成相应的代码框架,提高开发效率。
  • 文档生成:类图作为系统设计的可视化文档,便于团队成员之间的沟通和理解。
  • 系统维护:通过查看类图,可以快速理解系统的结构和类之间的关系,便于后期的维护和扩展。

三、设计模式与UML类图结合实例 🛠️

为了更深入地理解设计模式的七大原则和UML类图,我们通过具体的实例来展示如何在设计中使用这些原则,并通过类图进行表达。

1. 单一职责原则与类图

场景:在电商系统中,订单管理模块需要处理订单的创建、更新和状态跟踪。

问题:如果订单类既负责订单的管理,又负责订单状态的跟踪,会增加类的复杂性,违反单一职责原则。

解决方案:将订单管理和状态跟踪分离到不同的类中。

类图

@startuml
class Order {- id: String- items: List<Item>+ add_item(item: Item): void+ remove_item(itemId: String): void+ calculate_total(): float
}class OrderStatus {- status: String+ update_status(newStatus: String): void+ get_status(): String
}
@enduml

在这里插入图片描述

通过这样的设计,Order类专注于订单的管理,OrderStatus类专注于订单状态的管理,符合单一职责原则。

2. 开放封闭原则与类图

场景:在一个图形绘制系统中,需要支持多种图形的绘制,如圆形、矩形和三角形。

问题:如果每次新增图形都需要修改现有的绘图类,违反了开放封闭原则。

解决方案:通过定义一个绘制接口,让不同的图形类实现该接口。

类图

@startuml
interface Drawable {+ draw(): void
}class Circle implements Drawable {+ draw(): void
}class Rectangle implements Drawable {+ draw(): void
}class Triangle implements Drawable {+ draw(): void
}class DrawingTool {+ drawShape(shape: Drawable): void {shape.draw()}
}
@enduml

在这里插入图片描述

通过引入Drawable接口,DrawingTool无需修改即可支持新的图形类型,符合开放封闭原则。

四、类图在实际项目中的应用 🏗️

在设计模式和七大原则的应用中,UML类图不仅仅是一种理论工具,它在实际项目中有着广泛的应用。下面,我们将通过一个具体的案例来展示类图的实际应用,并进行深度优化和扩展。

案例:在线图书管理系统📚

背景:设计一个功能完善的在线图书管理系统,支持用户管理、图书管理、借阅管理、权限控制和系统配置等功能。

系统功能

  1. 用户角色管理(普通用户、管理员、VIP用户)
  2. 图书分类与标签管理
  3. 图书借阅与归还流程
  4. 借阅历史记录与统计
  5. 系统配置与权限控制
  6. 图书搜索与推荐

分析
根据系统功能,可以将系统划分为以下几个主要模块:

  • 用户管理模块(用户注册、登录、角色管理)
  • 图书管理模块(图书CRUD、分类、标签)
  • 借阅管理模块(借阅流程、归还、逾期处理)
  • 权限管理模块(角色权限控制)
  • 系统配置模块(全局配置管理)

类图设计

@startuml
' 用户相关类
interface User {+ register(): void+ login(username: String, password: String): boolean+ logout(): void+ updateProfile(profile: UserProfile): void
}class RegularUser implements User {- username: String- password: String- email: String- profile: UserProfile+ register(): void+ login(username: String, password: String): boolean+ logout(): void+ updateProfile(profile: UserProfile): void
}class AdminUser implements User {- username: String- password: String- permissions: List<Permission>+ register(): void+ login(username: String, password: String): boolean+ logout(): void+ updateProfile(profile: UserProfile): void+ managePermissions(): void
}class VIPUser implements User {- username: String- password: String- vipLevel: int- expiryDate: Date+ register(): void+ login(username: String, password: String): boolean+ logout(): void+ updateProfile(profile: UserProfile): void+ getVipBenefits(): List<String>
}class UserProfile {- firstName: String- lastName: String- phone: String- address: String- joinDate: Date
}' 图书相关类
class Book {- id: String- title: String- author: String- isbn: String- publisher: String- publishDate: Date- price: float- stock: int- category: BookCategory- tags: List<BookTag>- status: BookStatus
}class BookCategory {- id: String- name: String- parentCategory: BookCategory+ subCategories: List<BookCategory>
}class BookTag {- id: String- name: String+ relatedTags: List<BookTag>
}enum BookStatus {AVAILABLEBORROWEDRESERVEDLOSTMAINTENANCE
}' 借阅相关类
class BorrowRecord {- id: String- userId: String- bookId: String- borrowDate: Date- dueDate: Date- returnDate: Date- status: BorrowStatus- fineAmount: float
}enum BorrowStatus {ACTIVERETURNEDOVERDUELOST
}class Fine {- id: String- recordId: String- amount: float- dueDate: Date- paid: boolean
}' 系统管理相关类
class UserManager {+ registerUser(user: User): void+ loginUser(username: String, password: String): User+ logoutUser(userId: String): void+ updateUserProfile(userId: String, profile: UserProfile): void+ resetPassword(userId: String): void
}class BookManager {+ addBook(book: Book): void+ removeBook(bookId: String): void+ updateBook(book: Book): void+ searchBooks(keyword: String, filters: Map<String, String>): List<Book>+ getBookDetails(bookId: String): Book+ manageCategories(): void+ manageTags(): void
}class BorrowManager {+ borrowBook(userId: String, bookId: String): void+ returnBook(bookId: String): void+ renewBook(recordId: String): void+ getBorrowRecords(userId: String): List<BorrowRecord>+ calculateFine(recordId: String): float+ payFine(fineId: String): void
}class SystemConfig {- id: String- configKey: String- configValue: String- valueType: ConfigValueType+ updateConfig(key: String, value: String): void
}enum ConfigValueType {STRINGINTEGERBOOLEANFLOAT
}' 关系类
class Notification {- id: String- userId: String- message: String- type: NotificationType- isRead: boolean- createdAt: Date
}enum NotificationType {SYSTEMBORROWRETURNFINEPROMOTION
}' 类图关系
UserManager "1" --> "many" User
BookManager "1" --> "many" Book
BorrowManager "1" --> "many" BorrowRecord
BorrowManager "1" --> "many" Fine
User "1" --> "many" BorrowRecord
Book "1" --> "many" BorrowRecord
Book "1" --> "1" BookCategory
BookCategory "0..*" <-- "0..*" BookCategory : has subcategories
Book "0..*" --> "0..*" BookTag
BookTag "0..*" --> "0..*" BookTag : related to
SystemConfig "1" --> "many" ConfigValueType
User "1" --> "many" Notification
BorrowRecord "1" --> "1" Notification : generates
Fine "1" --> "1" Notification : generatesnote for User "用户基类接口\n定义所有用户类型\n的公共方法"
note right for RegularUser "普通用户\n具备基本借阅功能"
note right for AdminUser "管理员\n具备管理权限"
note right for VIPUser "VIP用户\n享受特殊权益"
note for Book "包含图书基本信息\n和状态管理"
note for BookCategory "支持多级分类\n树形结构"
note for BorrowRecord "记录借阅详情\n和状态变更"
note for Fine "逾期罚款管理"
note for Notification "系统通知\n多种类型"@enduml

完整类图:

在这里插入图片描述

增强说明

  1. 用户角色扩展
    • 新增VIP用户角色,支持不同等级的会员权益
    • 用户档案类UserProfile分离,便于扩展用户信息
  2. 图书管理增强
    • 图书分类支持多级树形结构
    • 添加图书标签系统,支持多对多关联
    • 图书状态枚举,更精确管理图书状态
  3. 借阅流程完善
    • 借阅记录状态机设计,支持ACTIVE/RETURNED/OVERDUE/LOST
    • 罚款系统设计,关联借阅记录
    • 续借功能支持
  4. 系统管理扩展
    • 配置管理系统,支持不同类型的配置值
    • 通知系统,关联多种事件类型
  5. 设计模式应用
    • 用户角色采用策略模式,便于扩展新角色
    • 图书分类采用组合模式,支持多级结构
    • 配置管理采用状态模式,灵活处理不同类型配置
  6. UML增强细节
    • 添加类注释note,说明设计意图
    • 使用枚举类型明确状态和类型
    • 关系标注更清晰,如"has subcategories"
    • 接口与实现分离更明确

系统架构优势

  1. 可扩展性
    • 新增用户角色只需实现User接口
    • 新增图书分类无需修改现有代码
    • 新增通知类型只需扩展NotificationType枚举
  2. 灵活性
    • 图书状态机设计支持复杂业务场景
    • 配置管理系统支持运行时修改
    • 多级分类支持灵活的图书组织方式
  3. 可维护性
    • 职责分离清晰,各模块独立演化
    • 接口隔离原则应用,降低耦合度
    • 类型安全设计,减少运行时错误
  4. 业务支持
    • 完整的借阅生命周期管理
    • 灵活的权限控制体系
    • 全面的系统监控能力

这个增强版的类图设计更加贴近实际项目的复杂需求,展示了如何通过UML类图表达复杂的业务逻辑和系统架构。通过合理的类设计和关系定义,可以构建出既满足当前需求又具备良好扩展性的系统架构。

五、总结与展望 🌟

设计模式的七大原则为我们的软件设计提供了宝贵的指导,帮助我们构建灵活、可维护和可扩展的系统。而UML类图作为一种可视化的建模工具,能够有效地表达系统的结构和类之间的关系,是实现良好设计的重要辅助工具。

核心价值回顾

  1. 设计模式七大原则
    • 单一职责原则:确保每个类只负责一项明确的职责
    • 开放封闭原则:对扩展开放,对修改关闭
    • 里氏替换原则:子类必须能够替换父类
    • 接口隔离原则:客户端不应依赖不需要的接口
    • 依赖倒置原则:依赖抽象而非具体实现
    • 迪米特法则:最小化类之间的耦合
    • 组合/聚合复用原则:优先使用组合而非继承
  2. UML类图价值
    • 可视化系统架构
    • 明确类间关系
    • 支持团队沟通
    • 辅助代码生成
    • 文档化系统设计

实际应用建议 📋

  1. 设计阶段
    • 先绘制UML类图规划架构
    • 应用七大原则指导类设计
    • 标注关键类和接口
  2. 开发阶段
    • 参考类图实现代码
    • 定期回顾设计是否符合原则
    • 使用工具自动生成部分代码
  3. 维护阶段
    • 通过类图快速理解系统
    • 基于类图进行重构
    • 使用类图记录变更历史

进阶实践 🚀

  1. 模式组合应用
    • 结合工厂模式+策略模式实现灵活算法
    • 使用观察者模式+模板方法实现事件驱动
    • 组合装饰器模式+代理模式增强功能
  2. 工具链集成
    • PlantUML + Maven插件实现自动化文档
    • StarUML + Git版本控制设计变更
    • ArchiMate + UML进行企业架构设计
  3. 质量保障
    • 设计评审时检查原则符合度
    • 单元测试验证接口契约
    • 静态分析工具检查耦合度

未来趋势 🔮

  1. AI辅助设计
    • 自动生成类图建议
    • 智能模式推荐
    • 设计缺陷检测
  2. 云原生适配
    • 微服务架构下的设计原则演变
    • 云原生模式库
    • 容器化设计模式
  3. 领域驱动设计(DDD)融合
    • 六边形架构与七大原则结合
    • 聚合根设计实践
    • 限界上下文划分

希望本文能够帮助你更好地理解和应用设计模式的七大原则,以及使用UML类图进行系统设计。在后续的项目中,不妨尝试将这些原则和工具融入到你的开发流程中,享受它们带来的益处。记住,优秀的设计不是一蹴而就的,而是在实践中不断迭代和完善的结果。


图标注释

  • 类名使用class关键字定义
  • 属性和方法在类内部以可见性 名称: 类型表示
  • 关系使用不同的箭头和线型表示
  • 多重性可以在连接线上使用数字或符号表示

关键词:设计模式、七大原则、单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则、依赖倒置原则、组合/聚合复用原则、UML类图、系统设计、软件工程

ML类图规划架构

  • 应用七大原则指导类设计
  • 标注关键类和接口
  1. 开发阶段
    • 参考类图实现代码
    • 定期回顾设计是否符合原则
    • 使用工具自动生成部分代码
  2. 维护阶段
    • 通过类图快速理解系统
    • 基于类图进行重构
    • 使用类图记录变更历史

进阶实践 🚀

  1. 模式组合应用
    • 结合工厂模式+策略模式实现灵活算法
    • 使用观察者模式+模板方法实现事件驱动
    • 组合装饰器模式+代理模式增强功能
  2. 工具链集成
    • PlantUML + Maven插件实现自动化文档
    • StarUML + Git版本控制设计变更
    • ArchiMate + UML进行企业架构设计
  3. 质量保障
    • 设计评审时检查原则符合度
    • 单元测试验证接口契约
    • 静态分析工具检查耦合度

未来趋势 🔮

  1. AI辅助设计
    • 自动生成类图建议
    • 智能模式推荐
    • 设计缺陷检测
  2. 云原生适配
    • 微服务架构下的设计原则演变
    • 云原生模式库
    • 容器化设计模式
  3. 领域驱动设计(DDD)融合
    • 六边形架构与七大原则结合
    • 聚合根设计实践
    • 限界上下文划分

希望本文能够帮助你更好地理解和应用设计模式的七大原则,以及使用UML类图进行系统设计。在后续的项目中,不妨尝试将这些原则和工具融入到你的开发流程中,享受它们带来的益处。记住,优秀的设计不是一蹴而就的,而是在实践中不断迭代和完善的结果。


图标注释

  • 类名使用class关键字定义
  • 属性和方法在类内部以可见性 名称: 类型表示
  • 关系使用不同的箭头和线型表示
  • 多重性可以在连接线上使用数字或符号表示

关键词:设计模式、七大原则、单一职责原则、开放封闭原则、里氏替换原则、接口隔离原则、依赖倒置原则、组合/聚合复用原则、UML类图、系统设计、软件工程

版权声明:本文为原创内容,如需转载,请注明出处。

在这里插入图片描述
在这里插入图片描述

相关文章:

设计模式7大原则与UML类图详解

设计模式7大原则与UML类图详解 引言 &#x1f31f; 在软件工程领域&#xff0c;设计模式和UML&#xff08;统一建模语言&#xff09;是提高代码质量、增强系统可维护性的重要工具。设计模式提供了解决软件设计中常见问题的通用方案&#xff0c;而UML则为我们提供了一种可视化的…...

如何分析动态采样引起的计划不稳定 | OceanBase SQL 调优实践

这篇博客涉及两个知识点&#xff0c;一个是动态采样&#xff0c;另一个是 DAS 执行。 用户的问题和相关结论 我们看看用户在OceanBase 社区论坛发帖中提出的疑问及其所得出的结论。 问题&#xff1a;收集统计信息之前&#xff0c;为什么会出现计划不稳定的情况&#xff1f; …...

NY321NY322美光闪存芯片NY323NY336

NY321NY322美光闪存芯片NY323NY336 在存储技术飞速发展的今天&#xff0c;美光科技的闪存芯片凭借其创新架构与高性能表现&#xff0c;已成为工业自动化、智能终端等领域的核心组件。本文将围绕技术解析、产品评测、行业趋势、应用案例及市场动态五大维度&#xff0c;深入探讨…...

HMDB51数据集划分

生成训练集、验证集和测试集 每个split文件应该包含&#xff1a; 训练集(id1): 70个视频测试集(id2): 30个视频未使用(id0): 剩余视频 这是一个70/30的训练/测试分割比例。标记为0的视频被排除在当前实验之外。实际上训练集&#xff08;id1&#xff09;&#xff0c;验证集&am…...

25、DeepSeek-R1论文笔记

DeepSeek-R1论文笔记 1、研究背景与核心目标2、核心模型与技术路线3、蒸馏技术与小模型优化4、训练过程简介5、COT思维链&#xff08;Chain of Thought&#xff09;6、强化学习算法&#xff08;GRPO&#xff09;7、冷启动**1. 冷启动的目的****2. 冷启动的实现步骤****3. 冷启动…...

CodeBuddy 打造响应式测试平台:ScreenLab 的诞生记

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 开发工具&#xff1a;CodeBuddy&#xff08;AI 代码伙伴&#xff09; 技术栈&#xff1a;Vue3 Vite 原生 CSS…...

STM32实战指南:SG90舵机控制原理与代码详解

知识点1【SG90的简述】 SG90是一款微型舵机&#xff08;Micro Servo&#xff09;&#xff0c;由TowerPro等厂商提供&#xff0c;广泛用于机器人&#xff0c;舵机云台&#xff0c;舵机控制教学等项目中。 1、基本参数 2、工作原理 SG90内部有电机&#xff0c;齿轮组&#xff…...

基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)

源码项目获取联系 请文末卡片dd我获取更详细的演示视频 系统介绍 基于Spring Boot和Vue的在线考试系统。为学生和教师/管理员提供一个高效、便捷的在线学习、考试及管理平台。系统采用前后端分离的架构&#xff0c;后端基于成熟稳定的Spring Boot框架&#xff0c;负责数据处理…...

开源RTOS(实时操作系统):nuttx 编译

开源RTOS&#xff08;实时操作系统&#xff09;&#xff1a;nuttx 编译 手册&#xff1a;Installing — NuttX latest documentation 源码&#xff1a;GitHub - apache/nuttx: Apache NuttX is a mature, real-time embedded operating system (RTOS) Installing The fir…...

C++学习:六个月从基础到就业——C++11/14:decltype关键字

C学习&#xff1a;六个月从基础到就业——C11/14&#xff1a;decltype关键字 本文是我C学习之旅系列的第四十二篇技术文章&#xff0c;也是第三阶段"现代C特性"的第四篇&#xff0c;主要介绍C11/14中的decltype关键字。查看完整系列目录了解更多内容。 引言 在现代C…...

【51】快速获取数码管段选表(含小数点)及字母表的工具(分享)

1 介绍 1.1 画面 1.2 用法 输入IO口和段码字母的映射关系&#xff0c;比如这里e4d5dp2&#xff0c;指的是bit4是e段&#xff0c;bit5是d段&#xff0c;bit2是小数点dp段。 然后选择有效电平&#xff08;1表示亮 or 0表示亮&#xff09;。 点击生成段码配置&#xff0c;即可得到…...

高频面试题(含笔试高频算法整理)基本总结回顾120

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

5月17日

这几天不知道为啥没更新。可能是玩得太疯了。或者是考试有点集中&#xff1f;&#xff1f; 线性代数开课了&#xff0c;英语昨天完成了debate 昨天中午debate结束我们就出去玩了&#xff0c;去的那里时光民俗&#xff0c;别墅很好&#xff0c;770平米&#xff0c;但是缺点是可…...

摩方 12 代 N200 迷你主机(Ubuntu 系统)WiFi 抓包环境配置教程

摩方12代N200迷你主机标配 Intel AX201无线网卡&#xff0c;支持 WiFi 6 协议&#xff08;802.11ax&#xff09;及蓝牙5.2。此网卡兼容主流抓包工具&#xff0c;但需注意&#xff1a; 驱动兼容性&#xff1a;Ubuntu 20.04及以上内核版本&#xff08;5.4&#xff09;默认支持AX2…...

从零开始:使用 PyTorch 构建深度学习网络

从零开始&#xff1a;使用 PyTorch 构建深度学习网络 目录 PyTorch 简介环境配置PyTorch 基础构建神经网络训练模型评估与测试案例实战&#xff1a;手写数字识别进阶技巧常见问题解答 PyTorch 简介 PyTorch 是一个开源的深度学习框架&#xff0c;由 Facebook&#xff08;现…...

应用层自定义协议与序列化

应用层自定义协议与序列化 应用层协议网络版计算器序列化和反序列化序列化反序列化 重新理解read、write、recv、send和TCP为什么支持全双工代码结构Jsoncpp特性安装序列化使用Json::Value的toStyledString方法使用Json::StreamWriter使用Json::FastWriter 反序列化使用Json::R…...

2025春训第二十场

问题 B: 狗是啥呀 题目描述 在神秘的地狱深处&#xff0c;有着一种神秘的犬类生物&#xff0c;据传这种生物长了x个脑袋&#xff0c;并且具有强大的生命力。由于见过它的人全都下落不明&#xff0c;至今没有人知道它的真面目。 一位勇士为了斩杀这奇怪的生物&#xff0c;来到地…...

分糖果--思维+while判断

1.从左到右只考虑右边一遍&#xff0c;再从右到左考虑左边一遍&#xff0c;相当于左右考虑了 2.然后关键是1遍不一定行&#xff0c;while循环直到成功 https://www.luogu.com.cn/problem/B4091 #include<bits/stdc.h> using namespace std; #define N 100011 typedef …...

[system-design] ByteByteGo_Note Summary

目录 通信协议 REST API 与 GraphQL gRPC 如何工作&#xff1f; 什么是Webhook&#xff1f; 如何提高应用程序接口的性能&#xff1f; HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC) SOAP vs REST vs GraphQL vs RPC 代码优先与应用程序接口优先 HTT…...

Flask项目实践:构建功能完善的博客系统(含评论与标签功能)

引言 在Python Web开发领域&#xff0c;Flask以其轻量级、灵活性和易用性赢得了众多开发者的青睐。本文将带您从零开始构建一个功能完善的博客系统&#xff0c;包含文章发布、评论互动和标签分类等核心功能。通过这个实战项目&#xff0c;您不仅能掌握Flask的核心技术&#xf…...

Python爬虫实战:获取1688商品信息

在电商领域&#xff0c;获取1688商品信息对于市场分析、竞品研究、用户体验优化等至关重要。1688作为国内领先的B2B电商平台&#xff0c;提供了丰富的商品资源。通过Python爬虫技术&#xff0c;我们可以高效地获取1688商品的详细信息&#xff0c;包括商品名称、价格、图片、描述…...

Canva 推出自有应用生成器以与 Bolt 和 Lovable 竞争

AI 目前是一个巨大的市场,每个人都想从中分一杯羹。 即使是 Canva,这个以拖放图形设计而闻名的流行设计平台,也在其 Canva Create 2025 活动中发布了自己版本的代码生成器,加入了 AI 竞赛。 但为什么一个以设计为先的平台会提供代码生成工具呢? 乍看之下,这似乎有些不…...

多平台屏幕江湖生存指南

UniApp 屏幕适配大师:多平台屏幕江湖生存指南 屏幕江湖:尺寸混战 屏幕适配就像是应对不同体型的客人:从迷你的手机屏,到标准的平板,再到巨大的电视屏幕,你的应用必须有如武林高手般的适应力。 ┌──────────────────────────────────…...

BootCDN介绍(Bootstrap主导的前端开源项目免费CDN加速服务)

文章目录 BootCDN前端开源项目CDN加速服务全解析什么是BootCDN技术原理与架构CDN技术基础BootCDN架构特点1. 全球分布式节点网络2. 智能DNS解析系统3. 高效缓存管理机制4. 自动同步更新机制5. HTTPS和HTTP/2协议支持 BootCDN的核心优势速度与稳定性开源免费资源丰富度技术规范遵…...

LeetCode 153. 寻找旋转排序数组中的最小值:二分查找法详解及高频疑问解析

文章目录 问题描述算法思路&#xff1a;二分查找法关键步骤 代码实现代码解释高频疑问解答1. 为什么循环条件是 left < right 而不是 left < right&#xff1f;2. 为什么比较 nums[mid] > nums[right] 而不是 nums[left] < nums[mid]&#xff1f;3. 为什么 right …...

刷leetcodehot100返航版--二叉树

二叉树理论基础 二叉树的种类 满二叉树和完全二叉树&#xff0c;二叉树搜索树 满二叉树 如果一棵二叉树只有度为0的结点和度为2的结点&#xff0c;并且度为0的结点在同一层上&#xff0c;则这棵二叉树为满二叉树。 节点个数2^n-1【n为树的深度】 完全二叉树 在完全二叉树…...

「Mac畅玩AIGC与多模态41」开发篇36 - 用 ArkTS 构建聚合搜索前端页面

一、概述 本篇基于上一节 Python 实现的双通道搜索服务&#xff08;聚合 SearxNG 本地知识库&#xff09;&#xff0c;构建一个完整的 HarmonyOS ArkTS 前端页面。用户可在输入框中输入关键词&#xff0c;实时查询本地服务 http://localhost:5001/search?q...&#xff0c;返…...

【LINUX操作系统】生产者消费者模型(下):封装、信号量与环形队列

1.封装、完善基于阻塞队列的productor-consumer module 前文中我们封装了自己的Mutex 【LINUX操作系统】线程同步与互斥-CSDN博客 按照老规矩&#xff0c;现在我们对同步与互斥的理解更进一步了&#xff0c;现在把这种面向过程的语言封装成面向对象的写法 1.1 封装条件变量 #p…...

项目管理学习-CSPM-4考试总结

前言 经过两个月左右时间的学习&#xff0c;今天&#xff08;2025年5月17日&#xff09;参加了CSPM-4的考试&#xff0c;仿佛回到了2011年参加软考高项的时候。中午12点考完出来后&#xff0c;手都是酸酸的。不过整体感觉还可以&#xff0c;和预想的差不多。CSPM-4的考试一共有…...

自己手写tomcat项目

一&#xff1a;Servlet的原理 在Servlet(接口中)有&#xff1a; 1.init():初始化servlet 2.getServletConfig()&#xff1a;获取当前servlet的配置信息 3.service():服务器&#xff08;在HttpServlet中实现&#xff0c;目的是为了更好的匹配http的请求方式&#xff09; 4.g…...

C语言—再学习(结构体)

一、建立结构体 用户自己建立由不同类型数据组成的组合型的数据结构&#xff0c;它称为结构体。 struct Student { int num; //学号char name[20]; //名字为字符串char sex; //性别int age; //年纪float score; //分数char addr[30]; 地址为字符…...

SpringBoot--自动配置原理详解

为什么要学习自动配置原理&#xff1f; 原因&#xff1a;在实际开发中&#xff0c;我们经常会定义一些公共的组件&#xff0c;提供各个团队来使用&#xff0c;为了使用方便&#xff0c;我们经常会将公共的组件自定义成starter&#xff0c;如果想自定义starter&#xff0c;必须…...

MiInsertPageInFreeList函数分析和MmFreePagesByColor数组的关系

第一部分&#xff1a; Color MI_GET_COLOR_FROM_LIST_ENTRY(PageFrameIndex, Pfn1); ColorHead &MmFreePagesByColor[ListName][Color]; 第二部分&#xff1a; #define MI_GET_COLOR_FROM_LIST_ENTRY(index,pfn) \ ((ULONG)(((pfn)->…...

Windows/MacOS WebStorm/IDEA 中开发 Uni-App 配置

文章目录 前言1. 安装 HBuilder X2. WebStorm/IDEA 安装 Uniapp Tool 插件3. 配置 Uniapp Tool 插件4. 运行 Uni-App 项目 前言 前端开发人员对 WebStorm 一定不陌生&#xff0c;但有时需要开发 Uni-App 的需求&#xff0c;就必须要采用 HBuilder X&#xff0c;如果不习惯 HBu…...

redisson分布式锁实现原理归纳总结

Redisson 分布式锁的实现原理主要依赖于 Redis 的 Hash 数据结构、Lua 脚本、发布订阅机制以及看门狗&#xff08;Watchdog&#xff09;机制&#xff0c;以下是核心要点总结&#xff1a; 1. 核心原理 • 互斥性与可重入性&#xff1a; 通过 Redis 的 Hash 数据结构保存锁的持…...

Ubuntu 添加系统调用

实验内容 通过内核编译法添加一个不用传递参数的系统调用&#xff0c;其功能可自定义。 &#xff08;1&#xff09;添加系统调用号&#xff0c;系统会根据这个号找到syscall_table中的相应表项。具体做法是在syscall_64.tbl文件中添加系统调用号和调用函数的对应关系。 &#…...

Olib 2.2.0 | 免费开源软件,无需注册登录即可从ZLibrary下载多语言电子书

Olib是一款专为书籍爱好者设计的免费开源软件&#xff0c;它允许用户无需注册或登录即可从ZLibrary高速下载各种语言的电子书。该软件支持上百种语言的电子书下载&#xff0c;非常适合需要多语言资源的读者和研究人员使用。Olib的操作界面非常直观&#xff0c;使得书籍的搜索与…...

c++动态链接库

1. 生成动态链接库 首先实现一个动态链接库的代码 // example.cpp #include <iostream> void sayHello() {std::cout << "Hello from shared library!" << std::endl; }int add(int a, int b) {return a b; }// example.h #pragma once void sa…...

HelloWorld

HelloWorld 新建一个java文件 文件后缀名为 .javahello.java【注意】系统可能没有显示文件后缀名&#xff0c;我们需要手动打开 编写代码 public class hello {public static void main(String[] args) {System.out.print(Hello,World)} }编译 javac java文件&#xff0c;会生…...

SVGPlay:一次 CodeBuddy 主动构建的动画工具之旅

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 背景与想法 我一直对 SVG 图标的动画处理有浓厚兴趣&#xff0c;特别是描边、渐变、交互等效果能为图标增添许…...

SLAM定位常用地图对比示例

序号 地图类型 概述 1 格栅地图 将现实环境栅格化,每一个栅格用 0 和 1 分别表示空闲和占据状态,初始化为未知状态 0.5 2 特征地图 以点、线、面等几何特征来描绘周围环境,将采集的信息进行筛选和提取得到关键几何特征 3 拓扑地图 将重要部分抽象为地图,使用简单的图形表示…...

强化学习中,frames(帧)和 episodes(回合)

在强化学习中&#xff0c;frames&#xff08;帧&#xff09;和 episodes&#xff08;回合&#xff09;是两个不同的概念&#xff1a; 1. 定义差异 Frame&#xff08;帧&#xff09;&#xff1a; 表示智能体与环境交互的单个时间步&#xff08;step&#xff09;&#xff0c;例如…...

HCIP第六次作业

一、拓扑图 二、需求 1、使用PreVal策略&#xff0c;确保R4通过R2到达192.168.10.0/24 2、使用AS_Path策略&#xff0c;确保R4通过R3到达192.168.11.0/24 3、配置MED策略&#xff0c;确保R4通过R3到达192.168.12.0/24 4、使用Local Preference策略&#xff0c;确保R1通过R2…...

高频面试题(含笔试高频算法整理)基本总结回顾110

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

数据湖与数据仓库融合:Hudi、Iceberg、Delta Lake 实践对比

在实时与离线一体化的今天,数据湖与数据仓库边界不断融合,越来越多企业选用如 Hudi、Iceberg、Delta Lake 等开源方案实现统一的数据存储、计算、分析平台。本篇将围绕以下关键点,展开实战对比与解决方案分享: ✅ 实时写入能力 ✅ ACID 保证 ✅ 增量数据处理能力 ✅ 流批一…...

OGG 更新表频繁导致进程中断,见鬼了?非也!

大家好&#xff0c;这里是 DBA学习之路&#xff0c;专注于提升数据库运维效率。 目录 前言问题描述问题分析解决方案后续 前言 最近几周一直遇到一个 OGG 问题&#xff0c;有一张表已更新就会中断 OGG 同步进程&#xff0c;本文记录一下分析过程以及解决方案。 问题描述 昨天…...

C++学习-入门到精通-【7】类的深入剖析

C学习-入门到精通-【7】类的深入剖析 类的深入剖析 C学习-入门到精通-【7】类的深入剖析一、Time类的实例研究二、组成和继承三、类的作用域和类成员的访问类作用域和块作用域圆点成员选择运算符(.)和箭头成员选择运算符(->)访问函数和工具函数 四、具有默认实参的构造函数重…...

非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡

非易失性存储技术综合对比&#xff1a;EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡 读写性能对比 存储类型读取速度写入速度随机访问能力最小操作单位NVRAM极快(~10ns)极快(~10ns)极优(字节级)字节EEPROM中等(~100ns)慢(~5ms/字节)优(字节级)字节NOR Flash快(~50ns)慢(~5ms/…...

数字化转型- 数字化转型路线和推进

数字化转型三个阶段 百度百科给出的企业的数字化转型包括信息化、数字化、数智化三个阶段 信息化是将企业在生产经营过程中产生的业务信息进行记录、储存和管理&#xff0c;通过电子终端呈现&#xff0c;便于信息的传播与沟通。数字化通过打通各个系统的互联互通&#xff0c;…...

ARM (Attention Refinement Module)

ARM模块【来源于BiSeNet】&#xff1a;细化特征图的注意力&#xff0c;增强重要特征并抑制不重要的特征。 Attention Refinement Module (ARM) 详解 ARM (Attention Refinement Module) 是 BiSeNet 中用于增强特征表示的关键模块&#xff0c;它通过注意力机制来细化特征图&…...