揭秘:让代码更优雅的七大面向对象设计秘诀


软件项目中,需求是不断变化的,需求也是项目中最难把控的,需求的变更也是无法避免的。我们写的软件程序,如何能实现拥抱变化,使我们的软件达到可维护和可复用,这是一代代软件工程师不断追寻的真理。

导致一个软件的可维护性较低的原因有四个:
1.过于僵硬(Rigidity):比如在系统中新增一个功能,会变得非常复杂,涉及到很多模块的调整,这就是系统僵硬的体现。
2.过于脆弱(Fragility):比如对程序中某一个地方的修改,导致看上去没有什么关系的其他地方产生了影响,修改的同时,没有人能预测改动会给系统带来什么风险。
3.复用率低(Immobility):比如想使用程序中已有的一段代码、函数、模块时,这些已有的代码总是依赖一大堆其它的东西,很难将它们独立出来使用。
4.粘度过高(Viscosity):如果一个系统设计,不能简单的复用一个类或者通过接口来实现扩展,想扩展一个系统功能,必须破坏原始架构,就是粘度过高。

一个好的系统设计应该有如下的性质:

1.可扩展性(Extensibility):可以很容易地在系统中加入一个新的功能。
2.灵活性(Flexibility):可以很容易的实现对某个代码的修改,而不担心对其他模块产生影响。
3.可插入性(Pluggability):可以很容易的将一个类抽出去复用,或者将另一个有同样功能的接口的类加入到系统里。

常用的面向对象设计原则有6个,这6大设计原则都是以可维护性和可复用性为基础的,这些原则并不是孤立存在的,它们相互依赖相互补充,遵循这些设计原则可以有效地提高系统的复用性,同时提高系统的可维护性。

8ea929dffffc97c0a8282b72b54fdfb5.png

1

开闭原则

(Open-Closed Principle,OCP)

1、开闭原则定义

开闭原则:一个软件实体如类、模块应该对扩展开放,对修改关闭。即在不修改软件实体的基础上去扩展其功能。

Open(Open for extension):软件实体的行为必须是开放的、支持扩展的,而不是僵化的。

Closed(Closed for modification):在对软件实体的功能进行扩展时,不能修改已有的程序模块。

绝大部分的设计模式都符合开闭原则,开闭原则要求开发人员可以在不修改系统中现有的功能代码的前提下,而实现对应用系统的软件功能进行扩展。即要求我们应尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。它是为了适应未来的变化而对现有开发设计进行约束的一个原则。

2、开闭原则分析

开闭原则对扩展开放,对修改关闭,并不意味着我们的代码不能做任何更改,底层模块的变更,必然导致高层模块进行适配调整。

开闭原则是最基础的一个原则,抽象化是开闭原则的关键。

1、通过接口或者抽象类对扩展进行约束,不允许出现在接口或者抽象类中不存在的public方法。

2、参数类型,引用对象尽量使用接口或者抽象类,而不是具体的实现类。

3、抽象层尽量保持稳定,一旦确定就不允许修改。

2

单一职责原则

(Single Responsibility Principle,SRP)

1、单一职责原则定义

单一职责原则的意思是:类的职责要单一,不能将太多的职责放在一个类中。单一职责原则要求一个接口或类只能有一个原因引起变化,也就是一个接口或者类只能有一个职责。

2、单一职责原则分析

单一职责原则是高内聚性原则,避免相同的职责(也称为功能)分散到不同的类中实现,避免一个类承担过多的职责。可以减少类之间的耦合。

单一职责原则适用于接口,类,同时也适用于方法,即一个方法尽可能只做一件事情。

一般单一职责原则很难在项目中体现,因为单一职责的标准是用“职责”和“变化原因”来衡量一个接口或者类设计的是否优雅,但是“职责”和“变化原因”是不可度量的,项目或需求不同,会有不同的体现。

再者,本来一个类可以实现的功能,按照单一职责拆分成多个类,然后再用聚合或者组合的方式耦合起来,这样增加了系统的复杂性。

因此,对应单一职责原则,不能一味地追求职责单一化,适可而止就行。

3

里氏替换原则

(Liskov Substitution Principle, LSP)

1、里氏替换原则定义

里氏替换原则的意思是:在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象,即凡是父类能出现的地方,子类都可以进行替代。

把基类替换成它的子类,程序将不会产生任务错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。

里氏替换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

2、里氏替换原则分析

里氏替换原则主要是针对继承的设计原则,它为良好的继承定义了一个规范。

1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。

2、子类可以增加自己特有的方法。

3、当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)可以放大(比父类方法的输入参数更宽松)。

4、当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)可以被缩小(比父类更严格)。

如果父类的某些方法在子类中已经不能使用,则建议断开父子继承关系,采用依赖,聚合,组合关系代替继承。

4

2

依赖倒置原则

(Dependency Inversion Principle, DIP)

1、依赖倒置原则定义

依赖倒置原则的意思是:高层模块不应该依懒底层模块,它们都应该依赖抽象,抽象不应该依赖于细节,细节应该依赖于抽象。

另外一种表述为:要针对抽象层编程,而不要针对具体实现类编程。

2、依赖倒置原则分析

1、如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要手段。

2、依赖倒置原则的常用实现方式之一是在代码中使用抽象类,而将具体类放在配置文件中。

类之间的耦合关系

1、零耦合关系

2、具体耦合关系

3、抽象耦合关系

依赖倒置原则要求客户端依赖与抽象耦合,以抽象方式耦合是依赖倒转原则的关键。

依懒倒置就是编写程序需要的是对现实世界的事物进行抽象,抽象的结果就是有了抽象类和接口,然后我们用抽象间的依懒代替了实实在在的实现类间的依赖。

依赖的三种写法

1、构造函数传递依赖对象,也叫构造函数注入

2、Setter方法传递依赖对象,也叫Setter依赖注入

3、接口声明依赖对象,也叫接口注入,就是在接口的方法参数中声明依赖对象。

5

接口隔离原则

(Interface Segregation Principle, ISP)

1、接口隔离原则定义

接口隔离原则的意思是:客户端不应该依赖那些它不需要的接口,一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。

接口隔离原则要求我们不要建立功能丰富的庞大接口,使用多个专门的接口来取代一个统一的接口。每一个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干。

接口隔离原则告诉我们:使用多个隔离的接口,比使用单个接口要好,尽量降低类之间的耦合度。

2、接口隔离原则分析

1、一个接口就只代表一个角色,每个角色都有它特定的一个接口。 

2、接口仅仅提供客户端需要的行为,即所需的方法,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。

3、使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。

6

迪米特法则

(Law of Demeter, LoD)

1、迪米特法则的定义

迪米特法则又称最少知识原则(Least Knowledge Principle, LKP),它有多种定义方法,其中几种典型定义如下:

1、不要和“陌生人”说话。

2、只与你的直接朋友通信。

3、 每一个软件实体对其他的实体都只有最少的知识,而且局限于那些与本实体密切相关的软件实体。

迪米特法则的意思是:一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。    

2、迪米特法则的分析

迪米特法则的核心观念就是创建松耦合的类。简单地说,迪米特法则就是指一个软件实体应当尽可能少地与其他实体发生相互作用。这样,当一个模块修改时,就会尽量少地影响其他的模块,扩展会相对容易。

在迪米特法则中,对于一个对象,其朋友包括以下几类:

(1) 当前对象本身(this);

(2) 以参数形式传入到当前对象方法中的对象;

(3) 当前对象的成员对象;

(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;

(5) 当前对象所创建的对象。

任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。

7

合成复用原则

(Composite Reuse Principle, CRP)

1、合成复用原则的定义

合成复用原则又称为组合/聚合复用原则(Composition/ Aggregate Reuse Principle, CARP),其定义如下:尽量使用对象组合,而不是继承来达到复用的目的。

合成复用原则就是指在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用其已有功能的目的。简言之:要尽量使用组合/聚合关系,少用继承。

2、合成复用原则的分析

在面向对象设计中,可以通过继承或者组合/聚合关系,在不同的环境中复用已有的设计和实现。

继承复用:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。又叫“白箱”复用。

组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。又叫“黑箱”复用。

组合/聚合可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少,因此一般首选使用组合/聚合来实现复用。

在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

8

3

结束语

软件设计的根本就是要应对需求的变化,实际项目中需求变化又是不可预料的,面向对象设计给我们总结了6大设计原则来应对未来的变化:

Single Responsibility Principle:单一职责原则

Open Closed Principle:开闭原则

Liskov Substitution Principle:里氏替换原则

Law of Demeter:迪米特法则

Interface Segregation Principle:接口隔离原则

Dependency Inversion Principle:依赖倒转原则

把这6个原则的首字母联合起来就是Solid(稳定的),也就是说把这6个原则结合起来使用就可以建立稳定、灵活、可扩展、可复用的系统。

82d8ae245e2ba92b9cb3ed4e737c9f68.jpeg

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

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

相关文章

接口数据脱敏实现方案

背景 敏感信息如手机号、身份证、邮箱等信息需要脱敏后展示给前台,如果需要查看,则需要申请权限,查询时需要记录操作日志。 方案 通过JsonSerializer和注解,在json序列化的时候做脱敏操作 此处使用redis存储了加密后的key和明…

认养小游戏功能介绍

认养小游戏通常模拟了真实的农业生产过程,让玩家能够在线上体验种植、养殖的乐趣。以下是一些常见的认养小游戏功能介绍: 选择认养的农产品:首先,玩家可以从游戏中提供的多种农产品中选择自己想要认养的种类,如蔬菜、…

【Java一些注解知识】

RequestMapping RequestMapping是Spring框架中的一个注解,用于将HTTP请求映射到特定的处理方法上。通过使用RequestMapping注解,我们可以指定处理方法应该处理的URL路径和HTTP请求方法。 下面是一个简单的示例: 假设我们有一个UserControl…

[wp]第一届 “帕鲁杯“ --应急响应

1.前言: 第一次做这么大规模的应急响应靶场,收获许多 2.拓补图: 3.资产清单 4.解题 1. 签到[堡垒机的flag标签的值] [BrYeaVj54009rDIZzu4O] 2. 提交攻击者第一次登录时间 2024/04/11/14:21:18 3. 提交攻击者源IP 192.168.1.4 4. 提交…

网络隔离状态下,如何可以安全高效地进行研发文件外发?

研发部门的数据传输通常需要保证数据的安全性、完整性和保密性,尤其是当涉及到公司的核心技术、产品设计、源代码等重要信息时。研发文件外发,即研发资料的外部传输,通常涉及到公司的核心技术和商业机密,因此需要采取严格的安全措…

LayaAir引擎全面支持淘宝小游戏、小程序、小部件的发布

在最新的3.1版本和2.13版本中,LayaAir引擎已经全面支持了淘宝小游戏、小程序和小部件的开发和发布。这一重大更新,标志着LayaAir引擎与电商巨头阿里巴巴旗下的淘宝平台形成生态合作,在为广大开发者提供更加强大、高效的跨平台开发工具和解决方…

c++11 标准模板(STL)本地化库 - 平面类别(std::money_get) - 从输入字符序列中解析并构造货币值

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 从输入字符序列中解析并构造货币值 std::money_get template<…

Unity-NGUI爆错以后-导致不能多次点击,UI假卡死问题解决方法

太久没用&#xff0c;忘了&#xff0c;NGUI好像易出错&#xff0c;就再次点击不了 导致打开了UI关闭不了&#xff0c;每次都要重启就比较烦&#xff08;说的就是那种美术团队&#xff0c;一个 UI 打开几十层&#xff09; 就好比【左上角&#xff0c;箭头】点第二次是退出不了了…

【Mac】Hype 4 Pro for Mac(HTML5动画制作软件)v4.1.17安装激活教程

软件介绍 Hype 4 Pro是一款专业的HTML5动画和交互式内容制作软件&#xff0c;适用于Mac平台。它的主要特点和功能包括&#xff1a; 1.HTML5动画制作&#xff1a; Hype 4 Pro提供了直观的界面和丰富的工具&#xff0c;帮助用户轻松创建各种复杂的HTML5动画效果&#xff0c;包括…

每天五分钟计算机视觉:使用极大值抑制来寻找最优的目标检测对象

本文重点 在目标检测领域,当模型预测出多个候选框(bounding boxes)时,我们需要一种方法来确定哪些候选框最有可能表示真实的目标。由于模型的不完美性和图像中目标的重叠性,往往会有多个候选框对应于同一个目标。此时,极大值抑制(Non-Maximum Suppression,NMS)技术就…

Isaac Sim 6 仅使用isaacsim中自带的工具进行语义分割、实例分割(学习笔记5.09)

一.概要 建立场景&#xff0c;给场景内的物体赋予语义&#xff0c;使用Replicator进行分割操作&#xff0c;从而获得带标签信息的mask掩码图&#xff0c;可作为数据集、验证集等训练使用。 二.具体操作步骤 场景部分 1.搭建一个基础场景 这里建议在搭建的时候就按类别分好类…

变配电工程 变配电室智能监控系统 门禁 视频 环境 机器人

一、方案背景 要真正了解无人值守配电房的运行模式&#xff0c;我们必须对“无人值守”这一概念有准确的理解。它并不意味着完全没有工作人员管理&#xff0c;而是通过技术设备和人机协作来确保配电房的正常运行。 利用变配电室智能监控系统&#xff0c;可以实时获得配电室各…

44.乐理基础-音符的组合方式-附点

内容参考于&#xff1a; 三分钟音乐社 首先如下图&#xff0c;是之前的音符&#xff0c;但是它不全&#xff0c;比如想要一个三拍的音符改怎样表示&#xff1f; 在简谱中三拍&#xff0c;在以四分音符为一拍的情况下&#xff0c;在后面加两根横线就可以了&#xff0c;称为附点…

基于Unity为Vision Pro 构建游戏的4个关键

为Vision Pro开发游戏时需要考虑的四个关键概念:输入的自然性、物理尺寸的真实匹配、交互空间的充足性以及Unity组件的有效利用。 AVP交互小游戏(Capsule Critters)作者分享了使用Unity构建的几个核心关键: Bounded - 游戏定义:Bounded(有限)是Unity的术语,指的是游戏作…

利用“AnaTraf“网络流量分析仪轻松诊断和优化网络

网络性能监测和诊断(NPMD)是网络管理和优化的重要环节,准确快速地定位和排除网络故障对于保障业务正常运转至关重要。作为一款专业的网络流量分析设备,AnaTraf网络流量分析仪凭借其强大的流量分析和故障诊断功能,为网络管理者提供了一个高效的网络优化解决方案。 全面掌握网络…

【Ubuntu18.04+melodic】抓取环境设置

UR5_gripper_camera_gazebo&#xff08;无moveit&#xff09; 视频讲解 B站-我要一米八了-抓取不止&#xff01;Ubuntu 18.04下UR5机械臂搭建Gazebo环境&#xff5c;开源分享 运行步骤 1.创建工作空间 catkin_make2.激活环境变量 source devel/setup.bash3.1 rviz下查看模…

如何判断nat网络?如何内网穿透

大家都清楚&#xff0c;如果你想开车&#xff0c;就必须要给车上一个牌照&#xff0c;随着车辆越来越多&#xff0c;为了缓解拥堵&#xff0c;就需要摇号&#xff0c;随着摇号的人数越来越多&#xff0c;车牌对于想开车的人来说已经成为奢望。在如今的IPv4时代&#xff0c;我们…

TODESK怎么查看有人在远程访问

odesk怎么查看有人在远程访问 Todesk作为一款远程桌面控制软件&#xff0c;为用户提供了便捷的远程访问与控制功能。但在享受这种便利的同时&#xff0c;许多用户也关心如何确保自己设备的安全&#xff0c;特别是如何知道是否有人在未经授权的情况下远程访问自己的电脑。本文将…

OpenAI 希望您对其人工智能模型的行为发表意见

OpenAI 公布了一套高级“生活”指南&#xff0c;称为模型规范&#xff0c;该指南将定期更新&#xff0c;并确定其 AI 模型&#xff08;例如 ChatGPT 和 DALL-E&#xff09;在某些情况下的行为方式。 他们发布了初稿&#xff0c;并询问使用其模型的公众和利益相关者&#xff08…

大模型LLM之SFT微调总结

一. SFT微调是什么 在大模型的加持下现有的语义理解系统的效果有一个质的飞跃&#xff1b;相对于之前的有监督的Pre-Train模型&#xff1b;大模型在某些特定的任务中碾压式的超过传统nlp效果&#xff1b;由于常见的大模型参数量巨大&#xff1b;在实际工作中很难直接对大模型训…