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

Java面向对象六大设计原则总结1

简介

         在Java面向对象设计中,遵循六大原则是确保代码质量、可维护性和可扩展性的关键。这六大原则分别是:单一职责原则(SRP)、开闭原则(OCP)、里氏替换原则(LSP)、接口隔离原则(ISP)、依赖倒置原则(DIP)和迪米特法则(LOD)。以下是对这六大原则的详细解释,并结合实例进行说明。

  • 单一职责原则。对类来说,即一个类应该只负责一项职责。

  • 开闭原则。对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有代码,使用接口和抽象类实现一个热插拔的效果。

  • 里氏替换原则。任何基类可以出现的地方,子类一定可以出现。实现抽象的规范,实现子父类相互替换。

  • 依赖倒置原则。针对接口编程,依赖于抽象而不依赖于具体。

  • 接口隔离原则。降低耦合度,接口单独设计,相互隔离。

  • 最少知道原则(迪米特法则)。一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。

1. 单一职责原则(SRP)

单一职责原则要求一个类只负责一个功能或者职责。这意味着一个类应该只有一个引起它变化的原因。

例子: 假设我们有一个User类,它负责用户的所有操作,包括用户信息的获取、更新和删除。如果我们将这些操作分散到不同的类中,每个类只负责一个职责,那么代码将更加清晰和易于维护。

// 原始设计
class User {
    void getUserInfo() {}
    void updateUser() {}
    void deleteUser() {}
}

// 遵循单一职责原则
class UserInfoService {
    void getUserInfo() {}
}

class UserService {
    void updateUser() {}
    void deleteUser() {}
}

2. 开闭原则(OCP)

开闭原则要求软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需要增加新功能时,应该通过扩展现有代码来实现,而不是修改现有代码。

例子: 假设我们有一个Shape接口和一个Circle类实现该接口。如果需要添加新的形状(如Square),我们可以通过扩展Shape接口和添加新的实现类来实现,而不需要修改现有的代码。

interface Shape {
    double calculateArea();
}

class Circle implements Shape {
    private double radius;
    public Circle(double radius) { this.radius = radius; }
    @Override
    public double calculateArea() { return Math.PI * radius * radius; }
}

// 添加新的形状
class Square implements Shape {
    private double side;
    public Square(double side) { this.side = side; }
    @Override
    public double calculateArea() { return side * side; }
}

3. 里氏替换原则(LSP)

里氏替换原则要求所有引用基类的地方,必须能透明地使用其子类。这意味着子类应该能够替换其基类而不影响程序的正确性。

例子: 假设我们有一个Bird类和一个Ostrich类继承自BirdOstrichBird的一种特殊类型,但它不能飞行。如果我们在代码中使用了Bird类型的变量,那么它可以指向Ostrich对象,而不会影响程序的正确性。

class Bird {
    void fly() { System.out.println("Flying"); }
}

class Ostrich extends Bird {
    @Override
    void fly() { throw new UnsupportedOperationException("Ostrich cannot fly"); }
}

// 使用里氏替换原则
Bird bird = new Ostrich();
bird.fly(); // 这里会抛出异常

4. 接口隔离原则(ISP)

接口隔离原则要求客户端不应该依赖它不需要的接口。也就是说,接口应该尽可能小,只包含客户端需要的方法。

例子: 假设我们有一个Animal接口,包含eat()fly()方法。如果某些动物(如Dog)不需要飞行能力,那么它们不应该实现fly()方法。

interface Animal {
    void eat();
    void fly(); // 这个方法对某些动物来说是多余的
}

// 遵循接口隔离原则
interface Eater {
    void eat();
}

interface Flyer {
    void fly();
}

class Dog implements Eater {
    @Override
    public void eat() {}
}

class Bird implements Eater, Flyer {
    @Override
    public void eat() {}
    @Override
    public void fly() {}
}

5. 依赖倒置原则(DIP)

依赖倒置原则要求高层模块不应该依赖低层模块,两者都应该依赖其抽象。抽象不应该依赖细节;细节应该依赖抽象。

例子: 假设我们有一个OrderService类依赖于PaymentProcessor类。我们可以将PaymentProcessor抽象为一个接口,并让具体的支付处理器实现该接口,从而降低耦合度。

interface PaymentProcessor {
    void processPayment(double amount);
}

class CreditCardPayment implements PaymentProcessor {
    @Override
    public void processPayment(double amount) {}
}

class OrderService {
    private PaymentProcessor paymentProcessor;

    public OrderService(PaymentProcessor paymentProcessor) {
        this.paymentProcessor = paymentProcessor;
    }

    public void processOrder(double amount) {
        paymentProcessor.processPayment(amount);
    }
}

6. 迪米特法则(LOD)

迪米特法则要求一个对象应该对其他对象有尽可能少的了解。也就是说,一个类应该只与它的直接朋友通信,而不应该知道它的朋友的朋友。

例子: 假设我们有一个Department类和一个Employee类。Department类不应该直接访问Employee类的内部细节,而是应该通过公共接口进行交互。

class Employee {
    private String name;
    public String getName() { return name; }
}

class Department {
    private List<Employee> employees = new ArrayList<>();

    public void addEmployee(Employee employee) { employees.add(employee); }

    public void printEmployeeNames() {
        for (Employee employee : employees) {
            System.out.println(employee.getName());
        }
    }
}


http://www.kler.cn/a/349537.html

相关文章:

  • HTML(快速入门)
  • SpringCloudGateWay和Sentinel结合做黑白名单来源控制
  • Windows系统本地部署deepseek 更改目录
  • CAPL与外部接口
  • 【C++高并发服务器WebServer】-9:多线程开发
  • 论文速读|Matrix-SSL:Matrix Information Theory for Self-Supervised Learning.ICML24
  • YOLOv11改进策略【卷积层】| HWD,引入`Haar小波变换`到下采样模块中,减少信息丢失
  • 阿里云+frp内网穿透工作站远程开机
  • git的提取和拉取有啥区别
  • 配置环境windows-IIS默认拒绝put,delete的解决方案
  • MySQL-约束Constraint详解
  • @SneakyThrows:简化Java异常处理的利器
  • 【Linux】解锁线程基本概念和线程控制,步入多线程学习的大门
  • vue+element的confirm提示消息文字变色和换行
  • 《TH-OCR:强大的光学字符识别技术》
  • Ubuntu-24.10无法安装Sunlogin-15.2的解决方案
  • Vue获取url上的参数
  • Javascript 使用 Jarvis 算法或包装的凸包(Convex Hull using Jarvis’ Algorithm or Wrapping)
  • Unity3D 同步怪物实体到客户端详解
  • Webpack 完整指南
  • QT事件与网络通信
  • 索引面试题总结
  • 多态对象的存储方案小结
  • git gui基本使用
  • vue3中 a-table设置某一个单元格的背景颜色
  • 机器学习:知识蒸馏(Knowledge Distillation,KD)