”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 面向实体的开发

面向实体的开发

发布于2024-08-06
浏览:928

Desenvolvimento Orientado a SOLID

在软件开发中,代码维护、扩展和灵活性对于项目的长期成功非常重要。 SOLID 原则的制定是为了指导开发人员创建更易于理解、修改和扩展的代码。在本文中,我们将分别讨论 5 个 SOLID 原则以及如何通过 Java 中的实际示例来使用它们。

1. 单一职责原则

单一职责原则 (SRP) 规定,一个类必须只有一个更改理由,即它必须在系统内具有单一职责。

// Antes de aplicar o SRP
class ProductService {
    public void saveProduct(Product product) {
        // Lógica para salvar o produto no banco de dados
    }

    public void sendEmail(Product product) {
        // Lógica para enviar um email sobre o produto
    }
}
// Após aplicar o SRP
class ProductService {
    public void saveProduct(Product product) {
        // Lógica para salvar o produto no banco de dados
    }
}

class EmailService {
    public void sendEmail(Product product) {
        // Lógica para enviar um email sobre o produto
    }
}

在示例中,我们将在数据库中保存产品的责任与发送有关产品的电子邮件的责任分开。这有利于未来的更改,因为发送电子邮件的更改不再影响产品保存逻辑。

2. 开闭原理

开放/封闭原则(OCP)建议软件实体(类、模块、函数等)应该对扩展开放,但对修改封闭。这是通过使用抽象和继承来实现的。

// Exemplo inicial violando o OCP
class AreaCalculator {
    public double calculateArea(Rectangle[] rectangles) {
        double area = 0;
        for (Rectangle rectangle : rectangles) {
            area  = rectangle.width * rectangle.height;
        }
        return area;
    }
}
// Exemplo após aplicar o OCP
interface Forma {
    double calculateArea();
}
class Rectangle implements Forma {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double calculateArea() {
        return width * height;
    }
}

class AreaCalculator {
    public double calculateArea(Forma [] formas) {
        double area = 0;
        for (Forma formas: formas) {
            area  = forma.calculateArea();
        }
        return area;
    }
}

在第二个示例中,最初 AreaCalculator 类直接依赖于 Rectangle 类。这意味着如果您想添加其他类型的形状,例如圆形或三角形,则需要修改 AreaCalculator 类,从而违反 OCP。通过创建 Shape 接口,AreaCalculator 类能够接收新的几何形状,而无需修改现有代码。

3.里氏替换原理

里氏替换原则(LSP)规定超类的对象必须可以被其子类的对象替换,而不影响系统的完整性。换句话说,子类的行为必须与超类的行为一致。

// Classe base
class Bird {
    public void fly() {
        // Método padrão que imprime "Flying"
        System.out.println("Flying");
    }
}

// Classe derivada que viola o LSP
class Duck extends Bird {
    @Override
    public void fly() {
        // Sobrescrita que imprime "Ducks cannot fly"
        System.out.println("Ducks cannot fly");
    }
}

问题:Duck 类重写了 Fly() 方法来打印“鸭子不能飞”,从而改变了 Bird 基类中定义的默认行为,即所有鸟都会飞(“飞行”)。这违反了 LSP,因为任何期望 Bird 对象或其子类会飞的代码都无法与 Duck 一起正常工作,而我们已经知道 Duck 不会飞。

// Classe derivada que respeita o LSP
interface Bird {
    void fly();
}
class Eagle implements Bird {
    @Override
    public void fly() {
        System.out.println("Flying like an Eagle");
    }
}
class Duck implements Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ducks cannot fly");
    }
}

通过这种方法,Eagle 和 Duck 可以在需要 Bird 的地方互换,而不会破坏 Bird 界面设定的期望。 Duck 抛出的异常显式地传达了鸭子不会飞的信息,而没有以可能导致代码中出现意外问题的方式修改超类的行为。

4. 接口隔离原则

接口隔离原则(ISP)建议类的接口应该特定于使用它们的客户端。这避免了需要实现客户端未使用的方法的“胖”接口。

// Exemplo antes de aplicar o ISP
interface Worker {
    void work();
    void eat();
    void sleep();
}

class Programmer implements Worker {
    @Override
    public void work() {
        // Lógica específica para programar
    }
    @Override
    public void eat() {
        // Lógica para comer
    }
    @Override
    public void sleep() {
        // Lógica para dormir
    }
}
// Exemplo após aplicar o ISP
interface Worker {
    void work();
}
interface Eater {
    void eat();
}
interface Sleeper {
    void sleep();
}
class Programmer implements Worker, Eater, Sleeper {
    @Override
    public void work() {
        // Lógica específica para programar
    }
    @Override
    public void eat() {
        // Lógica para comer
    }
    @Override
    public void sleep() {
        // Lógica para dormir
    }
}

在示例中,我们将 Worker 接口拆分为更小的接口(Work、Eat、Sleep),以确保实现它们的类仅具有它们需要的方法。这可以防止类必须实现与它们不相关的方法,从而提高代码的清晰度和内聚性。

5. 依赖倒置原则

依赖倒置原则(DIP)建议高层模块(例如实现主要业务规则的业务或应用程序类)不应依赖于低层模块(基础设施类,例如访问外部数据和支持高级操作的服务)。两者都必须依赖于抽象。

// Exemplo antes de aplicar o DIP
class BackendDeveloper {
    public void writeJava() {
        // Lógica para escrever em Java
    }
}
class Project {
    private BackendDeveloper developer;

    public Project() {
        this.developer = new BackendDeveloper();
    }
    public void implement() {
        developer.writeJava();
    }
}
// Exemplo após aplicar o DIP
interface Developer {
    void develop();
}
class BackendDeveloper implements Developer {
    @Override
    public void develop() {
        // Lógica para escrever em Java
    }
}
class Project {
    private Developer developer;

    public Project(Developer developer) {
        this.developer = developer;
    }
    public void implement() {
        developer.develop();
    }
}

Project 类现在依赖于抽象(Developer)而不是具体实现(BackendDeveloper)。这允许不同类型的开发人员(例如 FrontendDeveloper、MobileDeveloper)轻松注入 Project 类,而无需修改其代码。

结论

采用 SOLID 原则不仅可以提高代码质量,还可以增强您的技术技能、提高工作效率并促进您作为软件开发人员的职业道路。

版本声明 本文转载于:https://dev.to/womakerscode/desenvolvimento-orientado-a-solid-al7?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本号的替代方法,它是使用以下语法: https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js(google hosted...
    编程 发布于2025-02-07
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-02-07
  • 对象拟合:IE和Edge中的封面失败,如何修复?
    对象拟合:IE和Edge中的封面失败,如何修复?
    解决此问题,我们采用了一个巧妙的CSS解决方案来解决问题:高度:100%; 高度:auto; 宽度:100%; //对于水平块 ,使用绝对定位将图像定位在中心,以object-fit:object-fit:cover in IE和edge消除了问题。现在,图像将按比例扩展,保持所需的效果而不会失...
    编程 发布于2025-02-07
  • 如何在Java列表中有效计算元素的发生?
    如何在Java列表中有效计算元素的发生?
    计数列表中的元素出现在列表 中,在java编程中,列举列表中列举元素出现的任务来自列表。为此,收集框架提供了全面的工具套件。在这种情况下,Batocurrences变量将保持值3,代表动物列表中的“ BAT”出现的数量。 &&& [此方法是简单的,可以得出准确的结果,使其成为计算列表中元素出现的理...
    编程 发布于2025-02-07
  • 为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    为什么使用固定定位时,为什么具有100%网格板柱的网格超越身体?
    网格超过身体,用100%grid-template-columns 问题:考虑以下CSS和HTML: position:fixed; grid-template-columns:40%60%; grid-gap:5px; 背景:#eee; 当位置未固定时,网格将正确显示。但是,当...
    编程 发布于2025-02-07
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。可以将fd.append("fileToUpload[]", files[x]);方法用于此目的,允许您在单个请求中发送多个文件。 初始尝试 在JavaScript中,一种常见方法是:); 但是,此代码仅处理第一...
    编程 发布于2025-02-07
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    如何为JavaScript对象变量创建动态键,尝试为JavaScript对象创建动态键,使用此Syntax jsObj['key' i] = 'example' 1;将不起作用。正确的方法采用方括号:他们维持一个长度属性,该属性反映了数字属性(索引)和一个数字属性的数量。标准对象没有模仿这...
    编程 发布于2025-02-07
  • 如何从PHP服务器发送文件?
    如何从PHP服务器发送文件?
    将文件发送到user
    编程 发布于2025-02-07
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月份)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将...
    编程 发布于2025-02-07
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    在这里工作/},false); 不幸的是,答案是否。除非在Creation中存储对处理程序的引用。要解决此问题,请考虑将事件处理程序存储在中心位置,例如页面的主要对象,请考虑将事件处理程序存储在中心位置,否则无法清理匿名事件处理程序。 。这允许在需要时轻松迭代和清洁处理程序。
    编程 发布于2025-02-07
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-02-07
  • 微实验标准:它是评估系统性能的可靠工具吗?
    微实验标准:它是评估系统性能的可靠工具吗?
    [2代码或小型系统调用。它旨在确定特定操作完成所需的时间和资源。但是,了解Microbenching的作用和不涉及的是至关重要。什么是microbenchmarking是 的名称,Microbenchmarking着重于测量小型,特定的特定,特定的,特定的,特定的,特定的,特定的,特定的,特定的,特...
    编程 发布于2025-02-07
  • 如何有效地加入SQL中的表以从多列中检索数据?
    如何有效地加入SQL中的表以从多列中检索数据?
    [2 使用SQL Table Joins 从多个列中检索数据 本指南演示了如何有效地组合来自多个SQL表的数据以在各种列中检索信息。我们将重点介绍方法,突出显示其使用并解决Microsoft Access的特定注意事项。 [2 基于共享列值从两个或多个表中合并行。 结果表仅包含所有连接表中匹配的...
    编程 发布于2025-02-07
  • 为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    为什么Microsoft Visual C ++无法正确实现两台模板的实例?
    [2明确担心Microsoft Visual C(MSVC)在正确实现两相模板实例化方面努力努力。该机制的哪些具体方面无法按预期运行?背景:说明:的初始Syntax检查在范围中受到限制。它未能检查是否存在声明名称的存在,导致名称缺乏正确的声明时会导致编译问题。为了说明这一点,请考虑以下示例:一个符合...
    编程 发布于2025-02-07
  • 可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    可以在纯CS中将多个粘性元素彼此堆叠在一起吗?
    </main> <section> ,但无法使其正常工作,如您所见。任何洞察力都将不胜感激! display:grid; { position:sticky; top:1em; z-index:1 1 ; { { { pos...
    编程 发布于2025-02-07

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3