面向对象设计的五大原则:SOLID原则(聚合和耦合)_v0.1.0

2024-08-22 10:28

本文主要是介绍面向对象设计的五大原则:SOLID原则(聚合和耦合)_v0.1.0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 聚合、组合与耦合
    • 1. **聚合(Aggregation)**
    • 2. **组合(Composition)**
    • 3. **耦合(Coupling)**
    • 比较总结
    • 总结
  • 面向对象设计五大原则:SOLID原则
    • 1. 单一职责原则(Single Responsibility Principle,SRP)
      • 原则解释
      • 举例说明
        • 初始设计(不符合单一职责原则)
        • 改进后
    • 2. 开闭原则(Open/Closed Principle,OCP)
      • 原则解释
      • 举例说明
        • 初始设计(不符合开闭原则)
        • 改进设计(符合开闭原则)
    • 3. 里氏替换原则(Liskov Substitution Principle,LSP)
      • 原则解释
      • 举例说明
        • 初始设计(违反里氏替换原则)
        • 改进设计(符合里氏替换原则)
      • 遵循 LSP 的几个要点
      • 里氏替换原则的好处
    • 4. 接口隔离原则(Interface Segregation Principle,ISP)
      • 原则解释
      • 举例说明
        • 初始设计(违反接口隔离原则)
        • 改进设计(符合接口隔离原则)
      • 遵循 ISP 的几个要点
      • 接口隔离原则的好处
    • 5. 依赖倒置原则(Dependency Inversion Principle,DIP)
      • 原则解释
      • 举例说明
        • 初始设计(违反依赖倒置原则)
        • 改进设计(符合依赖倒置原则)
      • 遵循 DIP 的几个要点
      • 依赖倒置原则的好处

更新记录

时间版本内容修订者备注
2024/08/220.1.0创建henry.xu

聚合、组合与耦合

这三个概念虽然都与对象之间的关系有关,但它们在设计意图和应用场景上有显著不同。以下是对聚合、组合和耦合的整理和比较:

1. 聚合(Aggregation)

  • 定义: 聚合是一种“整体-部分”关系,其中整体对象包含或拥有部分对象,但部分对象的生命周期独立于整体对象。换句话说,部分对象可以在没有整体对象的情况下存在。

  • 关系: 整体和部分之间的关系是松散的。整体对象只是引用部分对象,而不强制要求部分对象依赖于整体。

  • 示例: 部门与员工的关系。部门(整体)可以拥有多个员工(部分),但员工可以独立于部门存在。如果一个员工离开部门,他仍然是一个独立的个体。

  • 应用场景: 适用于当部分对象需要在多个整体对象之间共享或复用,或部分对象的生命周期与整体不完全绑定的情况。

2. 组合(Composition)

  • 定义: 组合也是一种“整体-部分”关系,但它比聚合更紧密。组合中,部分对象的生命周期依赖于整体对象。如果整体对象被销毁,部分对象也会随之销毁。

  • 关系: 整体和部分之间的关系是紧密绑定的。部分对象无法独立于整体对象存在。

  • 示例: 汽车与引擎的关系。汽车(整体)包含引擎(部分),如果汽车被销毁,引擎也随之销毁,因为引擎依赖于汽车存在。

  • 应用场景: 适用于当部分对象必须严格依赖于整体对象存在,且不希望部分对象被其他整体对象共享的情况。

3. 耦合(Coupling)

  • 定义: 耦合描述的是两个或多个模块或类之间的依赖程度。高耦合意味着模块或类之间的依赖性强,低耦合则意味着它们之间的依赖性弱。耦合程度通常反映了系统的模块化和可维护性。

  • 关系: 耦合不一定是“整体-部分”关系,而是更广泛的模块或类之间的关联程度。耦合可以是由于依赖、继承、接口实现等多种原因引起的。

  • 示例: 假设有两个类 AB,如果 A 的实现严重依赖于 B,那么 AB 之间是高耦合的。如果 AB 之间仅通过接口通信且相对独立,则它们是低耦合的。

  • 应用场景: 在系统设计中,通常追求低耦合,以提高系统的模块化和灵活性,使得修改一个模块不会对其他模块产生过多影响。

比较总结

  • 聚合与组合: 这两者都描述了“整体-部分”关系,但聚合关系较为松散,部分对象可以独立于整体对象存在;而组合关系紧密,部分对象的生命周期完全依赖于整体对象。生命周期是描述一个对象或实体在系统中从创建到销毁所经历的各个阶段的概念。理解生命周期有助于有效管理资源,避免内存泄漏,控制系统复杂性,并编写更健壮的代码。

  • 聚合/组合与耦合: 聚合和组合主要描述类或对象之间的结构性关系,而耦合则描述类或模块之间的依赖程度。高耦合系统往往难以维护,而聚合和组合的合理使用可以帮助降低耦合度,使系统更易于扩展和维护。

总结

  • 聚合: 松散的“整体-部分”关系,部分对象可以独立存在。
  • 组合: 紧密的“整体-部分”关系,部分对象的生命周期依赖于整体。
  • 耦合: 类或模块之间的依赖程度,追求低耦合以提高系统的可维护性和灵活性。

理解这三者之间的关系和差异有助于设计更加模块化、灵活和可维护的软件系统。

面向对象设计五大原则:SOLID原则

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

单一职责原则(Single Responsibility Principle,SRP)是面向对象设计中的一个重要原则。它的核心思想是:一个类应该只有一个引起它变化的原因。换句话说,一个类应当只负责一项职责。这样设计的好处是提高了代码的可读性、可维护性和可扩展性。

原则解释

在软件开发中,“职责”可以理解为类的功能或用途。如果一个类负责太多的职责,当某一职责发生变化时,类可能需要修改。而修改类可能会影响它的其他职责,从而增加了代码出错的风险。

SRP 强调,每个类只应专注于一项职责。如果有多项职责,应该考虑将这些职责分离到不同的类中。这样,每当某一职责发生变化时,只需修改对应的类,而不必担心影响其他职责。

  • 作用对象:类
  • 作用: 降低耦合,聚合关系的清晰化;尽管单一职责原则有助于减少类内部的复杂性,但它并不能完全避免类之间的耦合。

举例说明

初始设计(不符合单一职责原则)

假设我们有一个用户管理系统的类 UserManager,它有以下职责:

  1. 处理用户数据(如创建用户、删除用户)。
  2. 发送电子邮件通知。
class UserManager:def create_user(self, username, email):# 处理创建用户的逻辑print(f"User {username} created.")self.send_email(email, "Welcome!", "Thanks for joining us!")def delete_user(self, username):# 处理删除用户的逻辑print(f"User {username} deleted.")def send_email(self, email_address, subject, body):# 发送电子邮件的逻辑print(f"Sending email to {email_address} with subject: {subject}")

在这个例子中,UserManager 类同时承担了用户管理和发送电子邮件的职责。如果将来发送电子邮件的逻辑发生变化(例如引入新的电子邮件服务),我们必须修改 UserManager 类,这就违背了单一职责原则。

改进后

我们可以将发送电子邮件的职责分离到另一个类 EmailService 中。

class EmailService:def send_email(self, email_address, subject, body):# 发送电子邮件的逻辑print(f"Sending email to {email_address} with subject: {subject}")class UserManager:def __init__(self, email_service):self.email_service = email_servicedef create_user(self, username, email):# 处理创建用户的逻辑print(f"User {username} created.")self.email_service.send_email(email, "Welcome!", "Thanks for joining us!")def delete_user(self, username):# 处理删除用户的逻辑print(f"User {username} deleted.")

现在,UserManager 类只负责用户管理,而 EmailService 类负责发送电子邮件。如果将来电子邮件服务发生变化,只需修改 EmailService 类即可,不需要改动 UserManager

通过将不同的职责分离到独立的类中,不仅可以提升代码的可读性,还能使代码更易于测试和维护。如果一个类负责的职责太多,当其中的某个职责发生变化时,整个类可能需要进行大规模的修改,这不利于代码的扩展性。SRP 帮助开发者创建更简洁、功能单一的类,从而提高代码的质量。

2. 开闭原则(Open/Closed Principle,OCP)

开闭原则(Open/Closed Principle, OCP)是面向对象设计的五大原则之一(即SOLID原则中的“O”)。它的核心思想是:软件实体(如类、模块、函数等)应该对扩展开放,对修改关闭。

原则解释

  • 对扩展开放:意味着当需求变化或增加时,我们应该能够通过增加新代码来扩展软件实体的功能,而不是修改已有的代码。
  • 对修改关闭:意味着在实现新功能或满足新需求时,不应该改变已经存在的代码。现有的代码一旦通过测试并投入使用,就应该被视为“封闭的”。
  • 作用对象:类,模块,函数等;
  • 作用:降低耦合的同时允许扩展,聚合关系的可扩展性;这个原则的主要目的是提高代码的可维护性和灵活性,避免因为修改已有代码而引入新的错误。

举例说明

假设我们要开发一个图形绘制程序,可以绘制不同的形状,例如圆形和矩形。最开始,我们可能会有一个简单的类来处理这些形状的绘制。

初始设计(不符合开闭原则)
def draw_circle():print("draw circle")def draw_rectangle():print("draw rectangle")def draw_item(item):if item == "circle":draw_circle()elif item == "rectangle":draw_rectangle()# 使用:
draw_item("circle")
draw_item("rectangle")

在这个设计中,通过 draw_item 方法来绘制不同的形状。但如果我们需要增加新的形状,比如三角形或五边形,我们就需要修改 draw_item 方法,添加新的条件判断。这违背了开闭原则,因为每次添加新功能都要修改已有代码。

改进设计(符合开闭原则)
from abc import ABC, abstractmethodclass Shape:@abstractmethoddef draw(self):passclass Circle(Shape):def draw(self):print("draw circle")class Rectangle(Shape):def draw(self):print("draw rectangle")# 使用:
shapes = [Circle, Rectangle]
for shape in shapes:shape().draw()

在这个改进的设计中,我们将不同的形状分别设计成独立的类,并且这些类都继承了抽象基类 Shape。每个形状类都实现了自己的 draw 方法。

  • 对扩展开放:当我们需要添加新的形状时,比如三角形,只需要创建一个新的类 Triangle 并实现 draw 方法,而不需要修改 Shape 类或其他形状类。
  • 对修改关闭:已经实现的 CircleRectangle 类不会因为我们添加新形状而被修改。

这种设计方式遵循了开闭原则,使得系统更容易扩展,并且减少了对已有功能的影响,从而提高了系统的稳定性和可维护性。

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

里氏替换原则(Liskov Substitution Principle, LSP)是面向对象设计的五大原则之一(即 SOLID 原则中的“L”)。它的核心思想是:子类对象应该能够替换掉基类对象,并且不改变程序的正确性

原则解释

  • 子类型替换:LSP 要求子类必须能够替代其基类而不影响程序的行为。换句话说,基类中的方法应该能够在子类中正确地实现,而不会导致系统行为的不一致。
  • 一致性:子类应当在行为上与基类保持一致。子类可以增加新的行为,但不能改变基类中已有行为的定义或语义。
  • 作用对象:类与其子类;
  • 作用:确保系统的可替换性、可扩展性和可维护性。遵循 LSP 可以避免子类引入的错误,保持系统行为的一致性。

举例说明

假设我们在开发一个计算面积的程序,有一个 Rectangle 类和一个 Square 类。最开始,我们可能设计了如下的类结构。

初始设计(违反里氏替换原则)
class Rectangle:def __init__(self, width, height):self.width = widthself.height = heightdef set_width(self, width):self.width = widthdef set_height(self, height):self.height = heightdef area(self):return self.width * self.heightclass Square(Rectangle):def set_width(self, width):self.width = widthself.height = widthdef set_height(self, height):self.width = heightself.height = heightdef print_area(rectangle):rectangle.set_width(5)rectangle.set_height(4)print(rectangle.area())# 使用:
rect = Rectangle(2, 3)
print_area(rect)  # 输出: 20square = Square(2, 2)
print_area(square)  # 输出: 16

在这个设计中,Square 类继承了 Rectangle 类,并且重写了 set_widthset_height 方法,以保证正方形的宽和高总是相等的。然而,这个设计违背了 LSP,因为当我们用 Square 替换 Rectangle 时,print_area 函数的行为发生了变化。

  • Rectangleprint_area 期望在设置宽度和高度后,计算一个普通矩形的面积。但对于 Square,在设置宽度后,高度会自动调整,这导致 area 的计算结果不同。
改进设计(符合里氏替换原则)

为了符合 LSP,我们应该避免让子类改变基类的行为。可以通过重新设计类结构,使用组合而非继承来解决这个问题。

class Shape:def area(self):passclass Rectangle(Shape):def __init__(self, width, height):self.width = widthself.height = heightdef area(self):return self.width * self.heightclass Square(Shape):def __init__(self, side):self.side = sidedef area(self):return self.side * self.sidedef print_area(shape):print(shape.area())# 使用:
rect = Rectangle(5, 4)
print_area(rect)  # 输出: 20square = Square(4)
print_area(square)  # 输出: 16

在这个改进设计中,RectangleSquare 都继承了 Shape 类,各自实现了自己的 area 方法。

  • 子类型替换:现在,无论传递 Rectangle 还是 Square 对象给 print_area 函数,程序的行为都符合预期。
  • 一致性SquareRectangle 的行为保持一致,各自计算自身的面积,而不会因类的不同导致不一致的行为。不一致的行为主要体现在 “修改一个属性导致另一个属性的意外改变”,这打破了对类行为的一致性预期,导致使用子类替换基类时,程序无法按照原来的逻辑正确运行。这正是违反里氏替换原则的体现。

遵循 LSP 的几个要点

  1. 行为一致性:子类不应改变基类中已经实现的行为,子类的行为应该是基类行为的扩展或特化,而不是反转或破坏。
  2. 方法重写:如果子类重写了基类的方法,重写的方法必须符合基类方法的预期和约定。
  3. 接口设计:当设计基类时,要确保其接口足够通用,子类能够方便地继承并扩展这些接口,而不会违反 LSP。

里氏替换原则的好处

  • 增强代码的可替换性:子类可以在不修改客户端代码的情况下替换基类,从而提高系统的灵活性。
  • 减少代码的耦合度:通过遵循 LSP,可以减少系统中不必要的耦合,降低代码的维护成本。
  • 提高系统的稳定性:遵循 LSP 可以避免子类引入的不一致行为,从而提高系统的稳定性和可靠性。

LSP 是面向对象设计中的关键原则之一,它保证了继承关系的正确性和一致性,有助于创建稳定且可扩展的系统。

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

接口隔离原则(Interface Segregation Principle, ISP)是 SOLID 原则中的“ I ”,它的核心思想是:客户端不应该被迫依赖它们不使用的接口。这意味着一个接口应该只包含客户所需的方法,避免包含那些不被使用的方法,从而使得接口更加专注和简洁。

原则解释

  • 接口的专一性:一个接口应该只包含一个特定功能的相关方法。接口中的方法应该是相关的,避免将不相关的功能集中到一个接口中。
  • 减少依赖:通过将接口划分成多个专门的接口,减少类对不必要接口的依赖。每个接口应该只提供客户端所需要的功能。
  • 接口的契约:每个接口应该清晰地定义一个合同,客户只需要知道接口提供了哪些功能,而不需要了解其他不相关的功能。

举例说明

假设我们在设计一个打印机系统,有一个 MultiFunctionPrinter 类,这个类实现了打印、扫描、复印等多种功能。我们可以设计如下的接口:

初始设计(违反接口隔离原则)
class MultiFunctionPrinter:def print_document(self, document):print("Printing document:", document)def scan_document(self, document):print("Scanning document:", document)def copy_document(self, document):print("Copying document:", document)class DocumentProcessor:def __init__(self, printer):self.printer = printerdef process(self, document):self.printer.print_document(document)# DocumentProcessor 不需要 scan_document 和 copy_document 方法# 但是由于接口不够专一,这里的设计就违背了 ISP

在这个设计中,DocumentProcessor 类依赖于 MultiFunctionPrinter 的接口,但它只需要 print_document 方法。由于 MultiFunctionPrinter 实现了多个不相关的功能,这导致 DocumentProcessor 被迫依赖它不需要的功能。

改进设计(符合接口隔离原则)

为了符合 ISP,我们应该将 MultiFunctionPrinter 的接口拆分成多个专门的接口,每个接口只包含特定的功能:

class Printer:def print_document(self, document):passclass Scanner:def scan_document(self, document):passclass Copier:def copy_document(self, document):passclass DocumentProcessor:def __init__(self, printer: Printer):self.printer = printerdef process(self, document):self.printer.print_document(document)

在改进设计中,PrinterScannerCopier 分别定义了专门的接口,DocumentProcessor 只依赖于 Printer 接口。这样,DocumentProcessor 只依赖于它需要的接口,避免了不必要的依赖。

遵循 ISP 的几个要点

  1. 接口分离:将一个大接口拆分成多个小接口,每个小接口只包含一个特定的功能。
  2. 客户端专用接口:设计接口时要考虑到客户的实际需求,确保接口提供的功能符合客户的要求。
  3. 避免冗余方法:接口中不应包含未被客户端使用的方法,避免将多个不相关的功能集中到一个接口中。

接口隔离原则的好处

  • 提高代码的可维护性:接口专一化使得类的职责更加明确,减少了不必要的依赖,提高了代码的可维护性。
  • 增强代码的灵活性:客户端只依赖于所需的接口,使得代码在需求变化时更加灵活。
  • 降低系统的耦合度:通过减少类对不必要接口的依赖,降低了系统的耦合度,使得系统更易于扩展和修改。

接口隔离原则有助于创建更加模块化和可维护的系统,通过减少类对不必要功能的依赖,提高了系统的灵活性和稳定性。

5. 依赖倒置原则(Dependency Inversion Principle,DIP)

依赖倒置原则(Dependency Inversion Principle, DIP)是 SOLID 原则中的“ D ”。它的核心思想是:高层模块不应依赖于低层模块,而应依赖于抽象抽象不应依赖于细节,细节应依赖于抽象。换句话说,这个原则要求高层模块和低层模块都应依赖于抽象接口,而不是具体的实现类,从而减少系统的耦合度,提高灵活性和可维护性。

原则解释

  • 高层模块依赖于抽象:系统中的高层模块(即业务逻辑模块)不应直接依赖于低层模块(即具体实现模块)。高层模块应该依赖于抽象接口,这样可以避免高层模块因为低层模块的变化而受到影响。
  • 抽象不依赖于细节:抽象接口应该定义高层模块和低层模块之间的契约,而具体的实现细节应该在低层模块中实现。抽象接口应提供对低层模块功能的抽象,而不依赖于具体的实现细节。
  • 细节依赖于抽象:具体实现应该依赖于抽象接口,而不是依赖于其他具体实现。这可以确保系统的具体实现可以随时被替换,而不会影响到依赖于这些接口的高层模块。

举例说明

假设我们在开发一个报告生成系统,有一个 ReportGenerator 类需要依赖一个 Printer 类来打印报告。最开始,我们可能设计了如下的类结构:

初始设计(违反依赖倒置原则)
class Printer:def print(self, document):print("Printing:", document)class ReportGenerator:def __init__(self, printer):self.printer = printerdef generate_report(self, data):document = f"Report: {data}"self.printer.print(document)

在这个设计中,ReportGenerator 直接依赖于 Printer 类的具体实现。这导致 ReportGeneratorPrinter 之间的耦合度较高。如果将来我们需要更改 Printer 的实现,可能会对 ReportGenerator 造成影响,从而导致系统的灵活性和可维护性降低。

改进设计(符合依赖倒置原则)

为了符合 DIP,我们应该引入一个抽象接口,使 ReportGeneratorPrinter 之间的依赖关系通过抽象接口来建立。

from abc import ABC, abstractmethodclass Printer(ABC):@abstractmethoddef print(self, document):passclass ConsolePrinter(Printer):def print(self, document):print("Printing to console:", document)class ReportGenerator:def __init__(self, printer: Printer):self.printer = printerdef generate_report(self, data):document = f"Report: {data}"self.printer.print(document)

在改进设计中,Printer 被定义为一个抽象接口(使用 ABCabstractmethod 进行定义),ConsolePrinterPrinter 接口的一个具体实现。ReportGenerator 只依赖于 Printer 抽象接口,而不是 ConsolePrinter 的具体实现。这样,当我们需要更改打印的实现方式时,只需创建一个新的实现类,而不需要修改 ReportGenerator 类。

遵循 DIP 的几个要点

  1. 使用抽象接口:高层模块和低层模块之间的依赖关系应该通过抽象接口来建立,避免直接依赖具体实现。
  2. 分离接口与实现:将接口和实现分开,使得具体实现可以在不改变高层模块的情况下进行替换或修改。
  3. 依赖注入:将依赖关系的注入(例如,通过构造函数注入)从高层模块中提取出来,以实现更好的模块解耦。

依赖倒置原则的好处

  • 增强系统的灵活性:通过依赖抽象接口而不是具体实现,使得系统可以更加灵活地进行扩展和修改。
  • 减少系统的耦合度:降低高层模块对低层模块的依赖,提高了系统的可维护性和稳定性。
  • 提高代码的可测试性:依赖于抽象接口使得系统组件更容易进行单元测试,因为可以通过模拟对象(mock objects)来替代具体的实现类进行测试。

依赖倒置原则有助于创建更加模块化和可扩展的系统,通过减少对具体实现的依赖,提高了系统的灵活性和可维护性。

这篇关于面向对象设计的五大原则:SOLID原则(聚合和耦合)_v0.1.0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096011

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

SprinBoot+Vue网络商城海鲜市场的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

Spring的设计⽬标——《Spring技术内幕》

读《Spring技术内幕》第二版,计文柯著。 如果我们要简要地描述Spring的设计⽬标,可以这么说,Spring为开发者提供的是⼀个⼀站式的轻量级应⽤开发框架(平台)。 作为平台,Spring抽象了我们在 许多应⽤开发中遇到的共性问题;同时,作为⼀个轻量级的应⽤开发框架,Spring和传统的J2EE开发相⽐,有其⾃⾝的特点。 通过这些⾃⾝的特点,Spring充分体现了它的设计理念:在

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

创业者该如何设计公司的股权架构

本文来自七八点联合IT橘子和车库咖啡的一系列关于设计公司股权结构的讲座。 主讲人何德文: 在公司发展的不同阶段,创业者都会面临公司股权架构设计问题: 1.合伙人合伙创业第一天,就会面临股权架构设计问题(合伙人股权设计); 2.公司早期要引入天使资金,会面临股权架构设计问题(天使融资); 3.公司有三五十号人,要激励中层管理与重要技术人员和公司长期走下去,会面临股权架构设计问题(员工股权激