面向对象的六大原则详细说明

面向对象编程中,有六大设计原则(也称 SOLID 原则),它们是软件设计的核心思想。遵循这些原则可以使代码更具扩展性、灵活性和可维护性。下面逐一介绍每个原则,并附带示例说明。

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

定义:一个类应该只有一个引起它变化的原因,即每个类都应该有一个单一的职责。

示例:假设有一个 User 类,用于处理用户的基本信息并负责将用户数据保存到数据库。此时 User 类包含了多种职责:用户信息管理和数据持久化。

违反单一职责的设计

class User {private String name;private String email;public User(String name, String email) {this.name = name;this.email = email;}public void saveToDatabase() {System.out.println("Saving user to database");// 数据库保存逻辑}
}

遵循单一职责原则的设计:将数据持久化的逻辑抽离到一个单独的 UserRepository 类中,让 User 仅负责用户数据管理。

class User {private String name;private String email;public User(String name, String email) {this.name = name;this.email = email;}
}class UserRepository {public void save(User user) {System.out.println("Saving user to database");// 数据库保存逻辑}
}

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

定义:软件实体(类、模块、函数等)应该对扩展开放,对修改关闭,即在不修改现有代码的情况下,扩展其行为。

示例:假设有一个 Shape 类,可以绘制不同形状的对象。如果以后要添加新的形状(如矩形、三角形),我们不应该修改原有代码。

不符合开闭原则的设计

class Shape {public void draw(String shapeType) {if (shapeType.equals("Circle")) {System.out.println("Drawing a circle");} else if (shapeType.equals("Square")) {System.out.println("Drawing a square");}}
}

符合开闭原则的设计:使用多态,将不同形状的绘制行为放在各自的子类中。

interface Shape {void draw();
}class Circle implements Shape {public void draw() {System.out.println("Drawing a circle");}
}class Square implements Shape {public void draw() {System.out.println("Drawing a square");}
}

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

定义:子类对象可以替换父类对象,且不会影响程序的正确性。

示例:假设有一个 Rectangle 类和一个 Square 类,Square 继承自 Rectangle。若不遵循里氏替换原则,Square 的行为可能与 Rectangle 不一致,从而导致错误。

违反里氏替换原则的设计

class Rectangle {protected int width, height;public void setWidth(int width) {this.width = width;}public void setHeight(int height) {this.height = height;}public int getArea() {return width * height;}
}class Square extends Rectangle {@Overridepublic void setWidth(int width) {this.width = this.height = width;}@Overridepublic void setHeight(int height) {this.width = this.height = height;}
}

改进设计:将 RectangleSquare 抽象为不同的类,不让 Square 继承 Rectangle

interface Shape {int getArea();
}class Rectangle implements Shape {protected int width, height;public Rectangle(int width, int height) {this.width = width;this.height = height;}public int getArea() {return width * height;}
}class Square implements Shape {private int side;public Square(int side) {this.side = side;}public int getArea() {return side * side;}
}

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

定义:不应强迫一个类实现它不需要的接口,即应将接口拆分为更小的、特定的接口。

示例:假设有一个 Worker 接口,其中包含了所有工作职责。如果 Worker 接口包含了 code 方法,所有实现了 Worker 的类都要实现该方法,这会导致不必要的实现。

违反接口隔离原则的设计

interface Worker {void work();void code();
}class Manager implements Worker {public void work() {System.out.println("Managing work");}public void code() {// 经理不需要实现编码工作}
}

符合接口隔离原则的设计:将 Worker 接口拆分为多个小接口。

interface Work {void work();
}interface Coding {void code();
}class Manager implements Work {public void work() {System.out.println("Managing work");}
}class Programmer implements Work, Coding {public void work() {System.out.println("Programming work");}public void code() {System.out.println("Writing code");}
}

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

定义:高层模块不应该依赖低层模块,两者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。

示例:假设有一个 Notification 类,直接依赖于 EmailSMS 的具体实现,这种设计违反了依赖倒置原则。

不符合依赖倒置原则的设计

class Email {public void send(String message) {System.out.println("Sending email: " + message);}
}class Notification {private Email email;public Notification() {email = new Email();}public void sendMessage(String message) {email.send(message);}
}

符合依赖倒置原则的设计:通过接口进行依赖注入,使 Notification 类依赖抽象而非具体实现。

interface MessageSender {void send(String message);
}class Email implements MessageSender {public void send(String message) {System.out.println("Sending email: " + message);}
}class Notification {private MessageSender messageSender;public Notification(MessageSender messageSender) {this.messageSender = messageSender;}public void sendMessage(String message) {messageSender.send(message);}
}

6. 迪米特法则(Law of Demeter, LoD)

定义:一个对象应当对其他对象有最少的了解,即只与直接的朋友交流,避免调用链式方法或非直接关联的对象。

示例:假设有一个 Customer 类,它直接调用 WalletgetBalance 方法,这是违反迪米特法则的。

违反迪米特法则的设计

class Wallet {private double balance;public Wallet(double balance) {this.balance = balance;}public double getBalance() {return balance;}
}class Customer {private Wallet wallet;public Customer(Wallet wallet) {this.wallet = wallet;}public double getCustomerBalance() {return wallet.getBalance();  // 直接访问 Wallet 的属性}
}

符合迪米特法则的设计:在 Customer 中添加一个获取余额的方法,避免直接访问 Wallet 的细节。

class Wallet {private double balance;public Wallet(double balance) {this.balance = balance;}public double retrieveBalance() {return balance;}
}class Customer {private Wallet wallet;public Customer(Wallet wallet) {this.wallet = wallet;}public double getBalance() {return wallet.retrieveBalance();  // 间接访问 Wallet}
}

总结

这六大设计原则在面向对象编程中相辅相成,有助于提高代码的结构化、模块化和可扩展性。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

信息收集系列(二):ASN分析及域名收集

内容预览 ≧∀≦ゞ 信息收集系列(二):ASN分析及域名收集前言一、ASN 分析1. 获取 ASN 码2. 使用 ASNMap 获取 IP 范围3. 将 IP 范围转化为 IP 列表 二、关联域名收集1. 顶级域(TLD)收集测试方法 2. 根域名收集常用方法…

揭秘:b站可以通过弹幕查询到发送者吗?答案是:不可行

查找发送者 发弹幕被找到 最近,我的一个好兄弟遇到了这样一个问题:他在b站发弹幕,结果被人找到了。他对此很困惑:“发送弹幕不是匿名的吗?只有评论才能看到用户名啊,难道发弹幕也可以被找到吗&#xff1f…

安装mysql、Navicat 17

1.安装mysql 下载地址 https://downloads.mysql.com/archives/installer/ 选择最新版本或者你需要的版本 点击第二个Download下载 下载完毕后双击启动,之后是这个页面 选Custom(第四个)自定义安装,可以将mysql安装到自定义目录…

人工智能助手是否让程序员技能退化?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

RecyclerView进阶知识讲解

在 Android 开发中,RecyclerView 是一种高效的列表和网格布局控件,用于显示大规模数据。尽管基本使用方法简单,但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面,我将从布局管理、动画和手势、自定义缓存、优化…

测试用例设计方法之判定表

测试用例设计方法之判定表 1. 为什么要有判定表方法2. 什么是判定表3. 判定表法设计用例步骤4. 判定表使用场景 1. 为什么要有判定表方法 案例: 验证"若用户欠费或者关机, 则不允许主被叫"功能的测试 说明: 等价类和边界值分析法主要关注单个输入类条件的测试并未考…

SpringCloud篇(服务拆分 / 远程调用 - 入门案例)

目录 一、服务拆分原则 二、服务拆分示例 1. 案例需求 2. 案例要求 3. 导入SQL语句 4. 实现思路 4.1. 创建父工程 cloud-demo 管理依赖 依赖导入思路 4.2. 创建子工程 order-servic 4.3. 创建子工程 user-servic 4.4. 创建 cloud_order 数据库和表并插入数据 4.5. …

特征融合篇 | YOLO11改进 | 更换上采样方式之轻量级通用上采样算子CARAFE

前言:Hello大家好,我是小哥谈。CARAFE算子的主要特点是在保持轻量级功能的同时,能够提供比其他上采样算子更好的性能。它通过少量的参数和计算量来实现高效的图像上采样。CARAFE算子能够根据像素之间的关系进行自适应的上采样,从而…

Java集合Queue——针对实习面试

目录 Java集合QueueQueue接口的特点是什么?Queue和Deque的区别?ArrayDeque和LinkedList的区别?什么是PriorityQueue?什么是BlockingQueue? Java集合Queue Queue接口的特点是什么? Queue接口在Java中是一个…

【支付宝崩了】复盘

一、背景 2024年11月11日,#支付宝崩了#冲上微博热搜第一 部分网友反映支付宝 App无法正常使用,他们遇到了同一笔订单被扣款三次、余额宝转账至余额后余额显示为0、线下支付后商家未收到款项但银行卡已被扣款等问题。 此外,有网友称支付…

丹摩征文活动|FLUX.1+ComfyUI的详细部署以及实验总结

公主请阅 1. FLUX.1的简介2. 部署过程创建资源ComfyUI的部署操作部署FLUX.1 如何使用?实验总结:环境搭建与工具安装实验步骤实验结果分析总结 1. FLUX.1的简介 FLUX.1 是由黑森林实验室开发的图像生成工具,分为三个版本: FLUX-1-…

基于STM32的智能仓库管理系统设计

引言 本项目基于STM32微控制器设计了一个智能仓库管理系统,通过集成多个传感器模块和控制设备,实现对仓库环境和物资管理的自动化监控。该系统能够实时监测仓库内的温湿度、烟雾浓度等参数,并且通过红外传感器监控人员出入,结合R…

206面试题(47~60)

208道Java面试题 47~60 **208道Java面试题****47. 在 Java 程序中怎么保证多线程的运行安全?****48. 多线程中 synchronized 锁升级的原理是什么?****49. 什么是死锁?****50. 怎么防止死锁?****51. ThreadLocal 是什么&#xff1f…

MySQl基础----Linux下数据库的密码和数据库的存储引擎(内附 实操图和手绘图 简单易懂)

绪论​ 涓滴之水可磨损大石,不是由于他力量强大,而是由于昼夜不舍地滴坠。 只有勤奋不懈地努力,才能够获得那些技巧。 ——贝多芬。新开MySQL篇章,本章非常基础,但同时需要一定的Linux基础,所以假若你没学习…

番外篇 | 关于YOLO11算法的改进点总结

前言:Hello大家好,我是小哥谈。在2024年9月27日盛大举行的YOLO Vision 2024活动上,Ultralytics公司震撼发布了YOLO系列的最新成员—YOLO11。作为Ultralytics YOLO系列实时目标检测器的最新迭代,YOLO11凭借尖端的准确性、速度和效率…

增长放缓,跨境电商如何以“体验”撬动高转化和高复购?

增长放缓, 跨境电商步入发展新周期 伴随着疫情红利的逐渐收缩,跨境电商市场从野蛮高速增长回归理性,步入新的发展周期,增幅放缓成为新常态。根据eMarketer的统计数据,全球跨境电商销售增长从2020年的26.7%下跌至2022年…

2024“龙信杯“电子数据取证竞赛——计算机取证题目Writeup

以下内容是2024年“龙信杯”电子数据取证竞赛计算机取证题目的答案与解题思路 前置 前置发现电脑中有EFS加密文件,故使用仿真软件保持原有密码进行仿真 1.分析计算机检材,嫌疑人在将其侵公数据出售前在Pycharm中进行了AES加密,用于加密的key…

Linux学习_12

第十一章 管理Linux软件包和进程 主要包括源码下载安装软件,PRM管理工具,YUM/DNF管理工具 源码下载安装软件 源码文件:是指包含计算机程序源代码的文本文件。源代码是用特定编程语言编写的人类可读指令,它描述了计算机程序的逻辑、…

2024年Python最新下载安装教程,附详细图文,持续更新

大家好,我是Java徐师兄,今天为大家带来的是Python3 的下载安装教程,适用于所有 Python3 版本,感兴趣的可以看一下 文章目录 简介一、Python的下载1 网盘下载地址 (下载速度比较快,推荐)2 官网下载地址 二、…

JAVA同城服务顺风车预约车拼车系统源码支持小程序+公众号+H5

JAVA同城服务顺风车预约车拼车系统源码,全面支持小程序、公众号及H5平台,精准定位于解决城市出行痛点,满足用户多样化、灵活化的出行需求。市场分析显示,该系统凭借便捷的预约拼车功能,有效缓解城市交通压力&#xff0…