软件设计--SOLID原则介绍--Java

133 阅读6分钟

软件设计--SOLID原则介绍--Java。在你的java或其他语言的编码过程中想想这个问题。

...这个故事将告诉你在编码时应该考虑的设计原则。这个例子将涵盖java。

为什么你应该使用坚实的原则?你如何将这些与你在java中的控制器、处理程序、动作、服务、存储库类联系起来。

单一责任原则

A 应该有 一个的责任,并且 只有 一个, 原因的理由 变化.

一个类应该只为一个目的服务,这并不意味着每个类应该只有一个方法 ,但它们都应该与该类的责任直接相关。

所有的方法属性 都应该为同一个目标而工作 。当一个类服务于多个目的责任 时,它应该被变成 一个新的类

这个类做得太多了

public class OrderProcessingModule {
    Order order = null;
    using (SqlConnection connection = 
    // Apply the changes to the Order from the OrderStatusMessage
    // International orders have a unique set of business rules
    // We need to treat larger orders in a special manner
    // Smaller domestic orders
    // Ship the order if it's ready
      // Transform the Order object into a Shipment 

你应该遵循单一责任原则 整个OrderProcessingModule类划分为一个相关类的子系统 ,每个类 履行自己的专门职责而不是 一大堆 代码。例如,你可以把所有的数据访问功能放到一个叫做OrderDataService 的新类中,而把订单业务逻辑放到另外一个类中。

单一责任原则的重点并不仅仅 编写更小的 方法。重点是每个类应该实现一组有凝聚力的相关功能。

遵循单一责任原则的一个简单方法 是不断地问自己,一个的每个方法操作 是否都与该类的名称直接相关。如果你发现有些方法与该类的名称不相符,你应该考虑将这些方法移到另一个类中。

开放-封闭原则

实体应该为扩展而开放,但为修改而封闭。

软件实体(类、模块、函数等)在不实际改变你所扩展的类的内容的情况下是可以扩展的。

如果我们能够足够强烈地遵循这一原则,那么就有可能在不触及任何一段原始代码的情况下修改我们的代码的行为。

例如,考虑这个类。

class Menu {

我们想遍历一个菜肴列表并返回它们的菜肴。

class Menu {
    getCuisines(dishName) {
}

函数getCuisines()不符合开放-封闭的原则,因为它不能针对新的菜肴种类进行封闭。

如果我们添加一个新的菜肴,比如说羊角面包,我们需要改变这个函数,添加新的代码,就像这样。

class Menu {
    getCuisines(dishName) {
}

如果你观察一下,对于每一种新的菜肴,都要在getCuisines()函数中添加一个新的逻辑。按照开放-封闭的原则,这个函数应该是开放的,可以扩展,而不是修改。

这里是我们如何使代码库符合OCP的标准。

class Menu {
class Burrito extends Menu {
class Pizza extends Menu {
class Croissant extends Menu {
function getCuisines(a: Array<dishes>) {
getCuisines(dishes);

这样,每当需要添加新的菜肴时,我们就不需要修改代码。我们只需创建一个类,然后用基类来扩展它。

利斯科夫替代原则

该原则围绕着父类和子类对象。按定义如下。

可替代性是 面向对象编程中的一个原则,说明在一个计算机程序中,如果S是T的一个子类型,那么T类型的对象可以被S类型的对象所替代。

简单地说,上述内容可以定义如下。

  • 如果我们有一个类T,并且有一个方法x的属性(例如圆形)。如果我们从类T中创建一个对象t,我们可以用t对x执行操作。
  • 如果我们有一个扩展了T的类S,那么S中的对象s应该能够执行x的方法。

不好的例子

public class Bird{

鸭子能飞,因为它是一只鸟,但这又如何呢。

public class Ostrich extends Bird{}

鸵鸟是一种鸟,但它不能飞,鸵鸟类是鸟类的一个子类型,但它不应该能使用飞的方法,这意味着我们破坏了LSP原则。

好例子

public class Bird{}

接口隔离原则

客户端不应该被迫依赖他们不使用的方法。

假设我们已经创建了一个简单的Set接口,如下图。

public 
boolean
boolean
E ceiling(E e);
E floor(E e);
}

创建一个TreeSet.java类,如下所示

public 
@Override
public 
@Override
public 
@Overridepublic 
@Override
public 
}

创建另一个类HashSet.java,如下所示。

public 
@Override
public 
return
}
@Override
public 
return
}
@Override
public 
// This method is not applicable for HashSet
return
}
@Override
public 
// This method is not applicable for HashSet
return
}
}

你看到这个问题了吗,尽管你不需要HashSet中的天花板和地板方法,但我们还是必须实现它们。
上述问题的正确解决方案是
:创建另一个名为NavigableSet的接口,该接口将具有上限和下限方法。

publicinterfaceNavigableSet {

E ceiling(E e);

E floor(E e);

}

记住保持简单,不要重复,你会发现你已经在不知不觉中使用了这个原则。

注意单一责任原则关注的是,而接口隔离原则关注的是接口

依赖反转原则

_"A. 高级模块不应依赖低级模块。两者都应该依赖抽象。
B. 抽象不应该依赖于细节。细节应该依赖于抽象"。
_

当你为下面的用例设计 REST API时,我将解释Solid原则的优势。当你写任何控制器、处理程序、服务和DTO创建时,你最好考虑一下并花点时间。

通常情况下,程序员习惯于匆匆忙忙地直接进行编码,我建议为你的设计 画一个蓝图分析 每个原则 ,验证蓝图 ,进行修改开始编码

注意事项

遵循S.O.L.I.D.原则的代码可以很容易地被共享、扩展、修改、测试和重构,没有任何问题。随着这些原则在现实世界中的应用,这些准则的好处将变得更加明显。

反模式和不正确的理解会导致愚蠢的代码。单子、紧密耦合、不可测试性、过早优化、描述性命名和重复。SOLID可以帮助开发者避免这些问题。


软件设计--SOLID原则介绍--Java.最初发表于Medium上的Javarevisited,在那里人们通过强调和回应这个故事继续对话。