坚实的原则:从面向对象编程开始
大家好,今天我想聊聊一些关于固体的东西。
固体?当然不是!没那么固体。
等等……啊,也许就是那么固体!
今天我去面试了,被问到关于“ Solid 原则”的问题。我的反应是“嗯……不太清楚”,意思是“我不知道你在说什么”。
走出面试官的房间时,我突然意识到自己确实需要研究一下 Solid 原则,才能在面向对象编程的道路上迈出正确的一步。
所以今天,我想用一些基本定义和简单的例子来介绍这个主题,以帮助我们全面理解这个概念。
1)是什么以及为什么:坚实的原则
SOLID 代表...
SOLID 是罗伯特·C·马丁 (Robert C. Martin) 提出的前五个面向对象设计 (OOD)**原则**的首字母缩写词。
它实际上只是我们在编码、改进和构建代码时需要牢记的一组原则。
SOLID 确实如此......
读完之后,我完全不明白它到底是什么意思。就我理解而言,这些原则旨在让开发人员能够更轻松、更清晰地开发软件,使其在规模越来越大、越来越复杂的情况下也易于维护和修改。因此,我们可以真正理解这个概念,它是一种面向对象编程的方法,即通过精简和重构的方式,减少不必要的部分,并组织代码。
2)深入研究:坚实的原则
第一条原则:单一职责原则
“一个类应该有且仅有一个改变的理由,这意味着一个类应该只有一项工作。”
这听起来很简单,意思是一个类应该只执行单一任务,而不是同一个类中的多个任务。
让我们看下面的例子。
class Book {
protected $Author;
public getAuthor($Author) {
return $this->Author;
}
public function formatJson() {
return json_encode($this->getAuthor());
}
}
你觉得怎么样?你觉得你掌握了吗?
我们可以清楚地看到,名为“Book”的类执行了多项操作,包括获取书籍作者信息,并将输出编码为 Json 格式。但是,如果我们想要输出 Json 以外的其他格式怎么办?在这种情况下,我们可能需要多写几行代码来添加更多方法或修改现有代码。目前看来,这似乎是一项小工作,因为我们现在的示例非常简单,但想象一下,如果有数百甚至数千个类,最好通过实施这些原则来提前避免混淆。
所以我们可以采取如下方法
class Book {
protected $Author;
public getAuthor($Author){
return $this->Author;
}
}
class JsonBookForm {
public function format(Book $Author) {
return json_encode($Author->getAuthor());
}
}
通过这样做,如果我们想要获得不同类型的输出,那么我们不需要直接在 Book 类中进行更改。
第二原则:开放封闭原则
“对象或实体应该对扩展开放,但对修改关闭。”
我知道这有点无聊,但这实际上意味着应该扩展类来改变功能,而不是修改类。当他们想要添加更多选项时,应该有一种扩展其功能的方式,而不是直接更改现有代码。
有一个常见的例子,如下所示。
class Triangle{
public $width;
public $height;
}
class Board {
public $triangles= [];
public function calculateArea() {
$area = 0;
foreach ($this->triangles as $triangle) {
$area += $triangle->width * $triangle->height* 1/2;
}
}
}
我们有一个 Triangle 类,它包含三角形的数据,即宽度和高度;还有一个 Board 类,它用作 Triangle 对象的数组。
这段代码目前看起来完全没问题,但当你考虑形状和面积计算函数时,也许以后你会想把这个函数用于其他形状,而不仅仅是三角形,以提高效率。目前,这几行代码无法做到这一点,因为它限制了 Board 类只能与 Triangle 类配合使用。
我们可以尝试的方法是
interface Shape {
public function area();
}
class Triangle implements Shape {
public function area() {
return $this->width * $this->height *1/2;
}
}
class Circle implements Shape {
public function area() {
return $this->radius * $this->radius * pi();
}
}
class Board {
public $shapes;
public function calculateArea() {
$area = 0;
foreach ($this->shapes as $shape) {
$area+= $shape->area();
}
return $area;
}
}
这样,我们就不需要在类名 Board 中指定类的名称,因此每当我们想要添加更多属性(例如 Rectangle)时,我们都可以轻松添加一个名为自己的类并实现 Shape 接口,以便我们可以在 Board 类中使用 area()。
第三原则:里氏替代原则
“设 q(x) 是关于类型 T 的 x 对象的可证明属性。那么 q(y) 应该对于类型 S 的对象 y 可证明,其中 S 是 T 的子类型。”
好吧,我知道这听起来确实像我高中数学老师说的。我不太明白。
不过看看这张图片, 是不是感觉很熟悉?我们可能在学校见过这张图片,而且我相信你的数学老师也一定提到过。这张图在我们的现实世界中可以隐含的东西与前面的例子有关。形状。
说到形状,有很多种,对吧?有圆形、三角形、长方形和正方形……等等,我们都知道长方形和正方形很像但不完全一样,对吧?
长方形包含正方形,因为长方形需要满足更多条件才能成为正方形。所以它会是这样的。
class Rectangle {
public function setW($w) {
$this->width = $w;
}
public function setH($h) {
$this->height = $h;
}
public function Area() {
return $this->height * $this->width;
}
}
class Square extends Rectangle {
public function set($w) {
$this->width = $w;
$this->height = $w;
}
public function setH=($h) {
$this->height = $h;
$this->width = $h;
}
}
但是您是否意识到有多行看起来完全一样?并且考虑到在本教程中,我们正在尽最大努力使代码可维护且高效,因此应该避免这种方式,而应尝试这种方式。
interface Setshape {
public function setH($h);
public function setW($w);
public function Area();
}
class Rectangle implements Setshape ;
class Square implements Setshape ;
通过这种方式,我们不必一遍又一遍地编写相同的代码,而只需简单地实现类的接口即可。
第四个原则:接口隔离原则
“客户端不应该被迫实现它不使用的接口,也不应该被迫依赖它不使用的方法。”
我们快到了,第四个原则意味着不应该强迫类实现它们不使用的接口。例如,假设有一些类看起来像
interface Employee {
public function generatereport()
public function clockin()
public function clockout()
public function customerservice()
public function getPaid()
}
假设有一位值班经理,他负责上述大部分功能,但不包括打卡上下班,因为他可能拿的是工资而不是按小时计酬,所以他永远不会使用这两个功能。为了再次遵循这个原则,我们应该这样做。
interface Generalemployee{
public function clockin()
public function clockout()
}
interface Employee{
public function customerservice()
public function getPaid()
}
interface management{
public function generatereport()
}
class Staff implements Generalemployee, Employee{
}
class Manager implements Employee, management{
}
最后一个原则:依赖倒置原则
“实体必须依赖于抽象,而不是具体。它指出高级模块不能依赖于低级模块,但它们应该依赖于抽象。”
我将直接讨论这个例子
class Getuserlists {
private $dbConn;
public function __construct(MySQLConn, $dbConn) {
$this->dbConn= $dbConn;
}
}
这是一个常见的错误,因为根据层次结构,Getuserlists 类是较高模块,而 MySQLConn 是较低模块,但是,您可以轻松注意到该类完全依赖于 MySQLConn,如果我们想使用不仅仅是 MySQL 的其他数据库,那么以后就会造成混淆。
因此,解决方案是......
interface DbConnectionInterface {
public function connect();
}
class MySqlConn implements DbConnectionInterface {
public function connect() {}
}
class Getuserlists {
private $dbConn;
public function __construct(DbConnectionInterface $dbConn) {
$this->dbConn= $dbConn;
}
}
根据上面的小片段,您现在可以看到高级模块和低级模块都依赖于抽象。
恭喜!!我们向面向对象编程的世界迈进了一步!!
结论
SOLID 原则一开始看起来非常令人困惑,为了使我能够轻松使用而不知不觉中,我仍然会遇到更多的困难,但有一些我们可以遵循的指导方针总是好的,不是吗?
文章来源:https://dev.to/ham8821/solid-principles-to-start-with-object-orient-programming-1e49