首页 >Java >java教程 >面向实体的开发

面向实体的开发

WBOY
WBOY原创
2024-07-24 16:37:00711浏览

Desenvolvimento Orientado a SOLID

在软件开发中,代码维护、扩展和灵活性对于项目的长期成功非常重要。 SOLID 原则的制定是为了指导开发人员创建更易于理解、修改和扩展的代码。在本文中,我们将分别讨论 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 基类中定义的默认行为,即所有鸟都会飞(“Flying”)。这违反了 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 原则不仅可以提高代码质量,还可以增强您的技术技能,提高工作效率,并促进您作为软件开发人员的职业道路。

以上是面向实体的开发的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn