面向对象编程

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 63w+ 字,讲解图 2808+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2200+ 小伙伴加入学习 ,欢迎点击围观

任何现实世界的对象,都有一些属性(可能会或可能不会随时间改变)和一些行为(可能会或可能不会根据其他条件而改变)。例如铅笔是真实世界的物体;它具有以下属性:

  • 颜色为红色(不会随时间变化)
  • 目前长度为 10 厘米(削尖时可能会改变)

它具有以下行为:

  • 正确使用会留下痕迹。
  • 标记可能会因施加的压力而异。 (取决于外部因素)
  • 锐化时它的长度会减少(恒定行为)

就像这个例子一样,现实世界的对象有更多的特性,但在编程中我们只满足所需的特性。

在 OOPS 中编程,有其自身的优势。例如,程序员更容易将对象与现实世界相关联并按预期进行编程。当应用程序变大并且有多个对象相互交互时,它真的很有帮助。它有助于在客观世界中分配责任,从而实现集中思考。

与 OOP(面向对象编程)相关的另一个重要特征是对象的分类。由于世界(真实/虚拟)充满了对象,因此很难将它们作为单独的对象进行管理。我们需要一种方法来对这些对象进行分类,帮助我们将不同的对象及其特征联系起来。例如黑色铅笔。它与前面示例中使用的完全相同,但是是不同的对象。但由于它们都是铅笔,所以它们属于同一类“铅笔”。而钢笔与铅笔非常相似,属于不同的类别。虽然,Pen和Pencil都是“书写工具”。

面向对象编程有以下原则:

抽象

抽象被定义为 处理想法而不是事件的质量 ,或者换句话说 ,从表征质量中解脱出来 。它使程序员能够专注于编程 什么 而不是 如何 编程。抽象可以看作是一种合约,用于公开我们提供的功能。使用这个概念可以隐藏实现细节。

例如,如果我们需要一个写的类,我们可以确定它必须有一个方法“write”


 abstract class writer{
   write();
}

因此,我们在这里所做的是,设计了一个抽象的高级类,即它知道我们需要“什么”功能,但是“如何”执行该功能超出了此类的范围。

这有很多优点

  • 我们向外部实体公开所需的最少信息,这有助于集中思考,避免混淆并防止意外承诺
  • 我们为未来留有改进的空间,如果实施细节被公开,这是不可能的。

继承

继承在一般英语中的意思是获得和传递。它早已存在于我们的文化中。父亲和祖先通过辛勤劳动获得土地,然后传给他们的孩子,甚至大自然也有利于继承。所有身体特征,如身高、皮肤/眼睛/头发颜色等,都受我们从父母那里继承的基因控制。这可以防止重新发明轮子并获得快速进步。 OOP 也是如此。我们创建了一个几乎没有基本属性/行为的父类。该父类的所有子类都将包含与父类相同的属性/行为。虽然,孩子可以获得更多的属性/行为或一起更改行为的实现。


 abstract class writer{
   write();
}

在上面的例子中,父类 (WritingInstrument) 有一个属性 color 和一个行为 write。当定义了子类(pen)后,就不需要再定义color和write了。它们在继承的帮助下出现在 pen 类中。但是,子类可以定义自己的附加属性/行为。

那么我们如何在实践中使用它呢?我们开发人员超级懒惰。我们不想一次又一次地输入一些东西。保留相同代码的多个副本也不是首选,因为

  • 它有助于代码管理,更少的副本意味着更少的代码
  • 一处变化随处可见
  • 更少的代码导致更少的错误
  • 当一个代码满足多个需求时实现泛化
  • 专注编码
  • 重点测试

Java 中的继承是通过 extends 或 implements 关键字实现的。


 abstract class writer{
   write();
}

多态性

多态这个词来源于两个词

  • Poly : 多个/多个
  • morph : 形式/形状

从字面上看,多态性一词是指对象在不同条件下表现不同的能力。

在编程中,可以在多个地方实现多态

  • 班级
  • 方法
  • 运营商
  • 以上所有内容在不同条件下可能表现不同,可能是它们被使用的上下文。这很有帮助,因为客户不需要了解多个方面,并且通过从上下文中选择所需的信息来实现所需的功能。

 abstract class writer{
   write();
}

 abstract class writer{
   write();
}

 abstract class writer{
   write();
}

 abstract class writer{
   write();
}

在上面的示例中,我们在 writingObjects 中有一个默认实现,它被子类 Pen 和 Pencil 扩展/覆盖。写入方法在 Main 类中被调用了 3 次。每次根据上下文中的对象调用不同的实现。在这里, write 方法具有多种行为,因此它是多态的。

封装

封装被定义为在单个单元中收集相关数据/功能。它有助于简化数据的访问/修改。例如,如果我们需要打印用户拥有的所有属性,我们有以下选项


 abstract class writer{
   write();
}

我们创建了一种接受所有特征并逐一打印它们的方法。随着项目列表数量的增加,识别正确字段的能力减弱,即使添加/删除单个字段,也会更改此方法的签名。因此,我们需要替换此方法的所有客户端,即使它们不需要新添加的字段。为了使代码更具可读性,并允许更容易修改,我们将属性封装在一个类中,并将其作为一个集合对象传递。


 abstract class writer{
   write();
}

 abstract class writer{
   write();
}

对象是变量和相关方法的软件包。您可以使用软件对象来表示真实世界的对象。您可能希望将现实世界中的狗表示为动画程序中的软件对象,或者将现实世界中的自行车表示为电动健身车中的软件对象。

在面向对象编程中,类是用于创建对象的可扩展程序代码模板,为状态(成员变量)和行为实现(成员函数、方法)提供初始值。

SOLID 首字母缩略词是由 Michael Feathers 为 Robert C. Martin 在 2000 年代初期命名的“前五项原则”引入的。当这些原则一起应用时,旨在使程序员更有可能创建一个易于维护和随时间扩展的系统。 SOLID 的原则是可以在开发软件时应用的指导方针,通过促使程序员重构软件的源代码直到它既易读又可扩展来消除代码异味。它是敏捷和自适应编程总体战略的一部分。

单一职责原则

在面向对象编程中,单一责任原则指出每个类都应该对软件提供的功能的单一部分负责,并且该责任应该完全由类封装。它的所有服务都应与该责任严格保持一致。

开闭原则

在面向对象编程中,开闭原则指出“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”;也就是说,这样的实体可以允许在不修改其源代码的情况下扩展其行为。

里氏替换原则

可替换性是面向对象编程中的一个原则。它指出,在计算机程序中,如果 S 是 T 的子类型,则类型 T 的对象可以用类型 S 的对象替换(即,类型 S 的对象可以替换类型 T 的对象)而不会改变任何期望的该程序的属性(正确性、执行的任务等)。

接口隔离原则

接口隔离原则 (Interface-segregation principle, ISP) 规定不应强迫任何客户端依赖它不使用的方法。 ISP 将非常大的接口拆分为更小和更具体的接口,以便客户只需了解他们感兴趣的方法。 ISP 旨在保持系统解耦,从而更容易重构、更改和重新部署。

依赖倒置原则

在面向对象编程中,依赖倒置原则是指一种特定形式的软件模块解耦。当遵循这一原则时,从高层的策略设置模块到低层的依赖模块建立的常规依赖关系被反转(即反转),从而使高层模块独立于低层模块的实现细节。该原则指出:

  • 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。
  • 抽象不应依赖于细节。细节应该依赖于抽象。

该原则颠覆了一些人对面向对象设计的看法,规定高级和低级对象必须依赖于相同的抽象。

掌握原则

一般责任分配软件模式(或原则),缩写为 GRASP,包含在面向对象设计中将责任分配给类和对象的指南。

控制器

控制器模式将处理系统事件的责任分配给代表整个系统或用例场景的非 UI 类。控制器:

  • 是负责接收或处理系统事件的非用户界面对象。
  • 应该用于处理单个(或相关的多个)用例的所有系统事件
  • 是控制系统操作的 UI 层之外的第一个对象。

除了控制事件流外,它本身不应该做太多工作

造物主

创建者类的职责是实例化和创建对象以供使用。它知道要创建什么对象,以及初始化值。有时创建者类会主动创建对象并将它们存储在缓存中,并在需要或请求时提供一个实例。

高内聚

高凝聚力是一种评估模式,它试图使对象适当地集中、可管理和可理解。高内聚一般用于支持低耦合。高内聚意味着给定元素的职责是强相关且高度集中的。将程序分解为类和子系统是增加系统内聚特性的一个例子。或者,低内聚是给定元素具有太多不相关职责的情况。低内聚的元素通常难以理解、难以重用、难以维护和不愿改变。

间接

间接模式通过将两个元素之间的中介责任分配给中间对象来支持两个元素之间的低耦合(和重用潜力)。这方面的一个例子是在模型-视图-控制器模式中引入了一个控制器组件,用于在数据(模型)及其表示(视图)之间进行调解。

资讯专家

信息专家(也称为专家或专家原则)是用于确定将责任委托给哪里的原则。这些职责包括方法、计算字段等。使用信息专家的原则,分配职责的一般方法是查看给定的职责,确定履行职责所需的信息,然后确定该信息的存储位置。 Information Expert 将负责将职责分配给最需要信息的班级。

低耦合

低耦合是一种评估模式,它规定了如何分配责任以支持:类之间的依赖性较低,一个类中的更改对其他类的影响较小,重用潜力较高。

多态性

根据多态性,定义基于类型的行为变化的责任被分配给发生这种变化的类型。这是使用多态操作实现的。

受保护的变体

Protected Variations 模式通过用接口包装不稳定的焦点并使用多态性创建该接口的各种实现来保护元素免受其他元素(对象、系统、子系统)的变化。

纯制作

Pure Fabrication 是一个不代表问题域中的概念的类,专门用于实现低耦合、高内聚和派生的重用潜力(当信息专家模式提供的解决方案没有时)。这种类在领域驱动设计中称为“Service”。

批评

Potok 等人的一项研究。已显示 OOP 和过程方法之间的生产率没有显着差异。

很难将 OOP 与其他技术(尤其是关系技术)进行批判性比较,因为缺乏对 OOP 的公认且严格的定义

克里斯托弗·J·达特

与其他语言(LISP 方言、函数式语言等)相比,OOP 语言没有独特的优势,并且会带来不必要的复杂性的沉重负担。

劳伦斯克鲁布纳

我发现 OOP 在技术上是不健全的。它试图根据在单一类型上变化的接口来分解世界。要处理实际问题,您需要多排序代数——跨越多种类型的接口族。我发现 OOP 在哲学上是不健全的。它声称一切都是对象。即使它是真的也不是很有趣——说一切都是一个对象根本就什么都没说。

亚历山大·斯捷潘诺夫

OOP 在大公司中的流行是由于“大量(且经常变化的)平庸程序员群体”。 OOP 强加的纪律防止任何一个程序员“造成太大的损害”。

保罗格雷厄姆

面向对象编程将名词放在首位。你为什么要竭尽全力把一个词性放在一个基座上?为什么一种概念优先于另一种概念?这并不是说 OOP 突然让动词变得不那么重要了,就像我们实际认为的那样。这是一个奇怪的倾斜视角。 史蒂夫耶格

Clojure 的创造者 Rich Hickey 将对象系统描述为现实世界的过于简单化的模型。他强调 OOP 无法正确建模时间,随着软件系统变得越来越并发,这个问题越来越严重。

Unix 程序员和开源软件倡导者埃里克·雷蒙德 (Eric S. Raymond) 一直批评将面向对象编程呈现为“一个真正的解决方案”的说法,并写道,面向对象编程语言倾向于鼓励厚层的程序,破坏透明度。 [42] Raymond 将此与 Unix 和 C 编程语言采用的方法进行了对比。

参考

玛格丽特劳斯@WhatIs.com

维基百科!

继承就是多态

SOLID(面向对象设计)

反对 OOPS 的 单一职责原则 论点

什么是 OOPS(没有炒作)

相关文章