深入理解Java面向对象设计的六大原则

目录

  1. 单一职责原则(SRP)

  2. 开放封闭原则(OCP)

  3. 里氏替换原则(LSP)

  4. 依赖倒置原则(DIP)

  5. 接口隔离原则(ISP)

  6. 迪米特法则(LoD)

  7. 结语

单一职责原则(SRP)

什么是单一职责原则

单一职责原则(SRP)指的是一个类应该只有一个引起变化的原因。通俗地讲,一个类应该只关注一个职责。如果一个类承担了过多的职责,那么在需求变化时,该类面临的变化可能会很复杂,从而影响代码的维护和扩展。

为什么要遵循单一职责原则

  1. 可读性:每一个类只负责一项职责,使得类的职责更加明确,代码更加可读。

  2. 可维护性:当类只有一个职责时,任何对应职责的变化都只会影响这个类,降低了维护成本。

  3. 可复用性:职责单一的类更容易被复用。

  4. 降低耦合:类与类之间的依赖关系减少,使得系统更加模块化。

代码示例

不遵循单一职责原则的代码:


public class Employee {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void calculateSalary() {// 计算工资的代码}public void saveToDatabase() {// 保存到数据库的代码}}

遵循单一职责原则的代码:


public class Employee {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}public class EmployeeSalaryCalculator {public void calculateSalary(Employee employee) {// 计算工资的代码}}public class EmployeeRepository {public void save(Employee employee) {// 保存到数据库的代码}}

总结

单一职责原则是设计一个易于维护和扩展的系统的重要基础。尽管在实际应用中可能会有一些妥协,但我们应尽量使每个类的职责单一。

开放封闭原则(OCP)

什么是开放封闭原则

开放封闭原则(OCP)是指一个软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。通俗地讲,当需求变化时,我们应通过扩展已有的代码,而不是修改已有的代码来实现变化。

为什么要遵循开放封闭原则

  1. 稳定性:对已有代码的修改可能引入新的bug,遵循OCP能提高系统的稳定性。

  2. 扩展性:通过扩展而非修改已有代码,使得系统更具扩展性,更容易适应新的需求。

  3. 可维护性:减少了对已有代码的修改,使得代码变得更加可维护。

代码示例

不遵循开放封闭原则的代码:


public class Shape {public void draw(String shapeType) {if (shapeType.equals("Circle")) {drawCircle();} else if (shapeType.equals("Rectangle")) {drawRectangle();}}private void drawCircle() {// 画圆的代码}private void drawRectangle() {// 画矩形的代码}}

遵循开放封闭原则的代码:


public interface Shape {void draw();}public class Circle implements Shape {@Overridepublic void draw() {// 画圆的代码}}public class Rectangle implements Shape {@Overridepublic void draw() {// 画矩形的代码}}public class DrawingService {private List<Shape> shapes;public DrawingService(List<Shape> shapes) {this.shapes = shapes;}public void drawShapes() {for (Shape shape : shapes) {shape.draw();}}}

总结

遵循开放封闭原则不仅提高了代码的可维护性和稳定性,同时也增加了系统的扩展能力。在实际开发中,我们应尽量遵循该原则,从而设计出更灵活、可扩展的系统。

里氏替换原则(LSP)

什么是里氏替换原则

里氏替换原则(Liskov Substitution Principle,LSP)是指在使用基类的地方可以透明地使用其子类,而不会导致程序错误。换句话说,子类对象应该能够替换其父类对象并且程序的行为不变。

为什么要遵循里氏替换原则

  1. 多态性:LSP是多态性的基础,通过子类替换父类,能够使得系统具备更好的灵活性和扩展性。

  2. 协作性:LSP保证了子类能够完全适应父类所定义的协作接口,使得系统能够更好地协作。

  3. 维护性:遵循LSP能够降低系统中的耦合度,使得代码更加容易维护。

代码示例

不遵循里氏替换原则的代码:


public class Bird {public void fly() {System.out.println("Bird is flying");}}public class Ostrich extends Bird {@Overridepublic void fly() {throw new UnsupportedOperationException("Ostrich cannot fly");}}

遵循里氏替换原则的代码:


public abstract class Bird {// Bird 公共行为}public interface Flyable {void fly();}public class Sparrow extends Bird implements Flyable {@Overridepublic void fly() {System.out.println("Sparrow is flying");}}public class Ostrich extends Bird {// Ostrich 特有行为}

总结

里氏替换原则是保证多态性的重要原则。遵循LSP能够使系统具备更好的扩展性和灵活性,同时也能够提高代码的可维护性和稳定性。

依赖倒置原则(DIP)

什么是依赖倒置原则

依赖倒置原则(Dependency Inversion Principle,DIP)指的是高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。

为什么要遵循依赖倒置原则

  1. 可扩展性:通过依赖于抽象,高层模块和低层模块的耦合度降低,从而增强了系统的可扩展性。

  2. 可维护性:修改低层模块的实现时,不会影响高层模块,使得系统更加易于维护。

  3. 模块重用性:增加系统各个模块的重用性,使得不同的模块可以组合使用。

代码示例

不遵循依赖倒置原则的代码:


public class Light {public void turnOn() {System.out.println("Light is on");}public void turnOff() {System.out.println("Light is off");}}public class Switch {private Light light;public Switch(Light light) {this.light = light;}public void operate(String command) {if (command.equals("ON")) {light.turnOn();} else if (command.equals("OFF")) {light.turnOff();}}}

遵循依赖倒置原则的代码:


public interface Switchable {void turnOn();void turnOff();}public class Light implements Switchable {@Overridepublic void turnOn() {System.out.println("Light is on");}@Overridepublic void turnOff() {System.out.println("Light is off");}}public class Switch {private Switchable device;public Switch(Switchable device) {this.device = device;}public void operate(String command) {if (command.equals("ON")) {device.turnOn();} else if (command.equals("OFF")) {device.turnOff();}}}

总结

依赖倒置原则是设计松耦合、高内聚系统的关键。通过依赖于抽象,我们能够使系统更加灵活和可维护。

接口隔离原则(ISP)

什么是接口隔离原则

接口隔离原则(Interface Segregation Principle,ISP)指的是客户端不应该依赖于它不需要的接口。换句话说,一个接口应该只提供客户端所需要的方法,避免将多个职责耦合在一起。

为什么要遵循接口隔离原则

  1. 提高耦合度:将接口分成多个小接口,使得客户端仅依赖于它需要的接口,降低了代码的耦合度。

  2. 提高可读性:更小的接口职责更加明确,提高了代码的可读性。

  3. 方便维护:修改某个接口时,不会影响到不需要该接口的客户端,从而提高了代码的维护性。

代码示例

不遵循接口隔离原则的代码:


public interface Worker {void work();void eat();}public class Developer implements Worker {@Overridepublic void work() {System.out.println("Developer is working");}@Overridepublic void eat() {System.out.println("Developer is eating");}}public class Robot implements Worker {@Overridepublic void work() {System.out.println("Robot is working");}@Overridepublic void eat() {throw new UnsupportedOperationException("Robot cannot eat");}}

遵循接口隔离原则的代码:


public interface Workable {void work();}public interface Eatable {void eat();}public class Developer implements Workable, Eatable {@Overridepublic void work() {System.out.println("Developer is working");}@Overridepublic void eat() {System.out.println("Developer is eating");}}public class Robot implements Workable {@Overridepublic void work() {System.out.println("Robot is working");}}

总结

接口隔离原则通过将大接口分割为小接口,使得客户端只依赖于它需要的接口,从而提高了代码的可读性和可维护性。

迪米特法则(LoD)

什么是迪米特法则

迪米特法则(Law of Demeter,LoD),又称最少知识原则(Principle of Least Knowledge,PLK),指的是一个对象应该对其他对象有尽可能少的了解。换句话说,一个对象应尽量少地与其他对象进行交互,避免过度耦合。

为什么要遵循迪米特法则

  1. 降低耦合:减少对象之间的过度依赖,降低系统的耦合度。

  2. 提高模块化:每个对象只关注自己的职责,提高了系统的模块化程度。

  3. 方便维护:减少了对象之间不必要的依赖关系,使得系统更易于维护和扩展。

代码示例

不遵循迪米特法则的代码:


public class Engine {public void start() {System.out.println("Engine started");}}public class Car {private Engine engine;public Car() {engine = new Engine();}public Engine getEngine() {return engine;}}public class Driver {public void drive(Car car) {car.getEngine().start();}}

遵循迪米特法则的代码:


public class Engine {public void start() {System.out.println("Engine started");}}public class Car {private Engine engine;public Car() {engine = new Engine();}public void start() {engine.start();}}public class Driver {public void drive(Car car) {car.start();}}

总结

迪米特法则通过减少对象之间的直接交互,降低了系统的耦合度,提高了系统的模块化和维护性。在设计系统时,应尽量遵循迪米特法则,从而避免过度耦合。

结语

通过深入理解和实践Java面向对象设计的六大原则,我们可以设计出更加优雅、可维护和可扩展的系统。尽管在实际应用中可能需要一些妥协,但这些原则为我们提供了设计高质量代码的指南。在今后的开发过程中,我们应尽量遵循这些原则,从而提升代码质量和开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/18681.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac快速搭建前端环境创建前端项目【Vue】

Mac快速搭建前端环境&创建前端项目 官网&#xff1a; vue&#xff1a;https://cn.vuejs.org/vue-router&#xff1a;https://www.axios-http.cn/pinia&#xff1a;https://pinia.vuejs.org/zh/getting-started.htmlaxios&#xff1a;https://www.axios-http.cn/ant-design&…

Advanced Installer 问题集锦

1、界面在主题中显示的图标&#xff0c;如logo、发布者名称、产品名称就算在设计界面时删除&#xff0c;但是下次打开工程依然存在 解决办法&#xff1a;“可见”属性设置为禁用 2、在不关闭软件的情况下&#xff0c;使用"文件->打开"来切换项目&#xff0c;再次…

c++按索引同时删除多个元素

文章目录 代码结果 这个时候不能从前往后删&#xff0c;因为会破坏後面的元素的索引值&#xff0c;比如如果第删除了第2个元素&#xff0c;第3个元素的索引就会变为第2个元素的索引&#xff0c;造成混乱&#xff0c;甚至引起程序崩溃。应该从後往前删。 代码 #include<iost…

学习笔记——数据通信基础——数据通信网络(基本概念)

数据通信网络基本概念 网络通信&#xff1a;是指终端设备之间通过计算机网络进行的通信。 数据通信网络(Data Communication Network)&#xff1a;由 路由器、交换机、防火墙、无线控制器、无线接入点&#xff0c;以及个人电脑、网络打印机&#xff0c;服务器等设备构成的通信…

软考 系统架构设计师系列知识点之杂项集萃(21)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;20&#xff09; 第30题 软件结构化设计包括&#xff08; &#xff09;等任务。 A. 架构设计、数据设计、过程设计、原型设计 B. 架构设计、过程设计、程序设计、原型设计 C. 数据设计、过程设…

探秘GPT-4o:人工智能语言模型的新纪元

目录 前言1 GPT系列版本演变1.1 GPT-1到GPT-3的演变1.2 GPT-4的引入 2 GPT-4o与GPT-4的区别2.1 参数规模和架构优化2.2 训练数据和方法改进2.3 多模态能力 3 GPT-4o在语言生成和理解方面的技术能力3.1 更自然的语言生成3.2 更深刻的语境理解3.3 强大的跨语言能力3.4 自适应学习…

服务器硬件基础知识全面解析

在信息技术领域&#xff0c;服务器作为支撑各类业务运行的基石&#xff0c;其稳定性和性能至关重要。服务器硬件作为服务器的核心组成部分&#xff0c;直接决定了其处理能力、可靠性和扩展性。本文将深入浅出地介绍服务器硬件的基础知识&#xff0c;帮助IT专业人士及对服务器技…

git都在自己的个人分支开发吗?功能分支和个人分支工作流

在实际的开发过程中&#xff0c;使用分支的策略可以根据项目的需求和团队的工作流程进行调整。以下是两种常见的分支策略&#xff1a; 1. 功能分支&#xff08;Feature Branches&#xff09; 每个功能或修复一个独立的分支。这种方法通常被称为“功能分支工作流”。 优点 隔…

如何通过手机自学编程入门:探索四、五、六、七方面的学习路径

如何通过手机自学编程入门&#xff1a;探索四、五、六、七方面的学习路径 在信息爆炸的时代&#xff0c;手机已不仅仅是通讯工具&#xff0c;更是知识的宝库和学习的利器。对于渴望入门编程的初学者来说&#xff0c;手机自学编程成为了一种便捷而高效的选择。本文将围绕四个方…

【Unity Shader入门精要 第11章】让画面动起来(一)

1. Unity Shader中的时间变量 Shader控制这物体的显示&#xff0c;当向Shader中引入时间变量后&#xff0c;就可以让物体的显示效果随时间发生变化&#xff0c;以实现动画效果。 Unity中常见的时间变量如下表&#xff1a; 变量类型描述_Timefloat4(t/20, t, 2t, 3t)&#xf…

gulp入门5:registry

在 Gulp 的上下文中&#xff0c;registry 通常不直接指代一个常规用户需要使用的功能&#xff0c;因为它更多地与 Gulp 的内部任务注册和管理机制相关。然而&#xff0c;Gulp 允许通过其插件系统来扩展和自定义任务注册表的行为。以下是一个关于 Gulp 中 registry 的深入教程&a…

## 揭开疾病预测的神秘面纱:面向医疗专业人士的sklearn逻辑回归逐步指南

引言 在当今数据驱动的医疗保健领域&#xff0c;机器学习已成为从患者数据中提取见解并做出明智决策的强大工具。在众多机器学习算法中&#xff0c;逻辑回归以其简单性、可解释性和解决分类问题的有效性脱颖而出。在本综合指南中&#xff0c;我们将深入研究逻辑回归的世界&…

打造高可用系统:深入了解心跳检测机制

本文作者:小米,一个热爱技术分享的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! Hello,大家好!我是你们的技术小伙伴小米,今天咱们来聊聊分布式系统中的“心跳检测”机制。心跳检测是一种简单而又重要的机制,用来监控系统的…

如何实现虚拟列表?定高和不定高两种场景

之前我写了一篇文章&#xff1a;如何使用 IntersectionObserver API 来实现数据的懒加载 在文章的最后&#xff0c;我们提到如果加载的列表数据越来越多&#xff0c;我们不可能把所有的数据都渲染出来&#xff0c;因为这样会导致页面卡住甚至崩溃。 为了优化这种长列表场景&am…

WebPack插件实现:打包之后自动混淆加密JS文件

在WebPack中调用JShaman&#xff0c;实现对编译打包生成的JS文件混淆加密 一、插件实现 1、插件JShamanObfuscatorPlugin.js&#xff0c;代码&#xff1a; class JShamanObfuscatorPlugin { apply(compiler) { compiler.hooks.emit.tapAsync(JShamanObfuscatorPlugin, (comp…

超级好用的C++实用库之跨平台实用方法

&#x1f4a1; 需要该C实用库源码的大佬们&#xff0c;可搜索微信公众号“希望睿智”。添加关注后&#xff0c;输入消息“超级好用的C实用库”&#xff0c;即可获得源码的下载链接。 概述 C跨平台开发时&#xff0c;我们经常会遇到一系列挑战和问题。这些问题主要源自不同操作…

Leetcode:两数之和

普通版本&#xff08;暴力枚举&#xff09; 题目链接&#xff1a;1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; //自己写的for循环 class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> res;bool flag …

浙江大学数据结构MOOC-课后习题-第九讲-排序3 Insertion or Heap Sort

题目汇总 浙江大学数据结构MOOC-课后习题-拼题A-代码分享-2024 题目描述 测试点 思路分析 和上一题的思路一样&#xff0c;每进行一次迭代&#xff0c;来验证当前序列是否和给定的序列相同 代码展示 #include <cstdlib> #include <iostream> #define MAXSIZE 10…

【PHP小课堂】PHP中的网络组件相关函数

PHP中的网络组件相关函数 作为一门以 WEB 开发为主战场的编程语言来说&#xff0c;PHP 即使是在目前这个大环境下&#xff0c;依然也是 WEB 领域的头号玩家。我们在网络相关的功能中也提供了许多方便好用的函数组件&#xff0c;而且它们都是不需要安装扩展就能够使用的。今天&a…

ubuntu-24.04系统静态Mac和IP配置

操作系统版本&#xff08;桌面版&#xff09;&#xff1a;ubuntu-24.04-desktop-amd64.iso 原因说明&#xff1a;因网络的IP地址和Mac是预分配的&#xff0c;所以ubuntu系统需要修改网卡的mac地址和IP才能访问&#xff0c;网络查了半天资料都没成功&#xff0c;后再界面提示&a…