前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >漫谈模式之违反S.O.L.I.D设计原则的示例

漫谈模式之违反S.O.L.I.D设计原则的示例

原创
作者头像
孟君
发布2023-04-21 08:35:00
6530
发布2023-04-21 08:35:00
举报

今天我们来看下违反设计原则的示例。

单一职责原则

含义

单一职责原则(Single Responsibility Principle,SRP):一个类只负责一个功能领域中的相应职责或可以定义为:就一个类而言,应该只有一个引起它变化的原因。

违反SRP原则的示例

图片
图片
图片
图片

在这个示例中,Person类包含了一个名为Wallet的成员变量,并且该类还包含了两个方法来添加和删除钱包中的金额。

这违反了SRP原则,因为Person类应该只负责表示一个人的信息,而不应该与钱包的操作有关。应该将钱包的操作单独封装到一个Wallet类中,让Person类只负责人的信息。

符合SRP原则的示例

图片
图片

在这个示例中,Person类仅包含一个名为Wallet的成员变量,而不包含任何关于钱包的操作。这里将钱包的操作单独封装到Wallet类中,让Person类只负责人的信息。

这样,当需要修改钱包的操作时,只需修改Wallet类即可,而不会影响到Person类的实现。

图片
图片

开闭原则

意图

开闭原则就是说对扩展开放,对修改关闭。

违反OCP原则的示例

如果在一个类中使用了switch语句来判断不同的情况,当需要添加一个新的情况时,必须修改源代码,这是违反OCP的。

图片
图片

符合OCP原则的示例

那么为了满足开闭原则,需要怎么做呢?那就要对系统采用抽象化设计抽象化是开闭原则的关键。

这个示例遵循OCP原则,因为它将支付方式的处理逻辑封装在不同的实现了Payment接口的类中。

图片
图片
图片
图片
图片
图片

当需要添加新的支付方式时,只需要创建一个新的实现了Payment接口的类即可,不需要修改任何现有的类。

图片
图片

PaymentProcessor类负责处理支付,它只需要知道传入的Payment实例,不需要知道具体的支付方式。

图片
图片

里氏替换原则

意图

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。里氏代换原 则中说,任何基类可以出现的地方,子类一定可以出现。

违反LSP原则的示例

图片
图片

在这个示例中,Square类继承自Rectangle类,但是在Square类中重写了setWidth和setHeight方法,从而违反了LSP原则,因为在Square类中,setWidth和setHeight方法的实现与Rectangle类中的实现不同。

在Rectangle类中,setWidth和setHeight方法应该只分别设置矩形的宽度和高度,但是在Square类中,这两个方法却同时设置了矩形的宽度和高度,导致Square类的行为与Rectangle类不一致。

图片
图片

符合LSP原则的示例

在这个示例中,Shape类是一个通用的形状类,Rectangle类和Square类都继承自Shape类,并且实现了各自的getArea方法。

图片
图片
图片
图片

这里没有让Square类继承自Rectangle类,而是让它们都继承自Shape类。

图片
图片

这样,当需要添加其他形状时,只需创建一个新的类继承自Shape类,并且实现自己的getArea方法即可,而不会对Rectangle类和Square类的实现造成影响。

接口隔离原则

意图

每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

违反ISP原则的示例

图片
图片

在这个示例中,我们定义了一个Animal接口,它包含了三个方法:eat、sleep和fly。

我们有两个实现类Dog和Bird,它们都实现了Animal接口。

图片
图片

然而,Dog并不能飞,因此它的fly方法只是抛出了一个不支持的操作异常。

在这种情况下,我们违反了ISP原则,因为Animal接口强制实现所有的方法,包括不适用于某些实现类的方法。

图片
图片

符合ISP原则的示例

在这个示例中,我们将Animal接口拆分成了两个接口:Animal和Flyable。

图片
图片
图片
图片

Animal接口包含与动物相关的方法,Flyable接口包含与飞行相关的方法。

我们有两个实现类Dog和Bird,它们分别实现了需要的接口。这个设计符合ISP原则,因为每个接口只包含所需的方法,没有多余的方法。

图片
图片

这样,我们可以根据需要选择实现哪个接口,而不需要实现不需要的方法。同时,我们也避免了实现不适用于某些实现类的方法。

图片
图片

依赖倒转原则

意图

面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

违反DIP原则的示例

在这个示例中,EmailService类依赖于具体实现的SmtpClient类。当我们需要使用不同的邮件传输协议时,EmailService类就不能很好地适应变化。

这是因为EmailService类的实现细节与SmtpClient类的实现细节耦合在一起,导致难以修改。

图片
图片
图片
图片

符合DIP原则的示例

为了遵循DIP原则,我们需要对这个示例进行重构。一种解决方法是使用依赖注入,将SmtpClient对象作为构造函数参数传递给EmailService类。

图片
图片
图片
图片

这样,EmailService类不再依赖于具体实现,而是依赖于抽象。

图片
图片

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单一职责原则
  • 开闭原则
  • 里氏替换原则
  • 接口隔离原则
  • 依赖倒转原则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档