【翻译】5个Java Class 设计原则-S.O.L.I.D.,设计原则-s.o.l.i.d
【翻译】5个Java Class 设计原则-S.O.L.I.D.,设计原则-s.o.l.i.d
【翻译】5个Java Class 设计原则-S.O.L.I.D.
原文地址:5 Class Design Principles (S.O.L.I.D.) in Java
Java类就像是组成Java应用程序大厦的砖块,如果这些砖块不够强壮,那么Java的应用大厦在使用中将会面对很多困难。本质就是说,随着Java应用范围的扩大,或者生产和运维中应用所面临特定的设计问题时,写的不够好的Java类将会带来很多难以解决的问题,如:性能问题、可维护性问题等。
另一方面,一系列设计和编写良好的Java类可以通过跳跃的方式加速编码过程,并在一定程度上减少bug的数量。
在本篇文章中,我们将讨论5个最受推崇的设计原则,当我们在编写程序是应该牢记于心的。这些设计原则被简称为SOLID。它们也形成了我们设计应用时应遵循的最佳实践。
S.O.L.I.D. Java Class 设计原则
原则名称 | 原则描述 |
---|---|
单一责任原则 (Single Responsibility Principle) |
一个类有且仅有一个责任(被修改的原因) |
开闭原则 (Open Closed Principle) |
软件组件应该对扩展开放,对修改关闭 |
里氏替换原则 (Liskov’s Substitution Principle) |
衍生类可以替换基类 |
接口隔离原则 (Interface Segregation Principle) |
客户端不应该被强迫实现其不需要使用的方法,即,一个类对另一个类的依赖应该建立在最小的接口之上 |
依赖反转原则 (Dependency Inversion Principle) |
依赖于抽象,而不依赖于具体的实现。反转指底层具体的实现和上层的应用均依赖于中间的抽象层 |
深入分析One by One
1. 单一责任原则(Single Responsibility Principle)
从单一责任原则的字面意思来看:
"一个类有且仅有一个职责"
也就是说:我们只针对一个目的去编写、修改和维护一个Java类。如果一个类是模型类,那么它应该严格地代表且仅代表一个实体。遵循单一责任原则可以给类的修改提供足够的灵活性,而不用担心会对其他实体产生影响。
类似地,如果我们编写一个服务/管理类,它应该仅包含需要调用的方法。该类甚至不包含与该模型相关的全局工具函数,这些全局方法应该被隔离在另一个全局访问的类文件中。这样有助于我们对类的维护,我们还可以针对具体的模型来确定其可见性。
2. 开闭原则(Open Closed Principle)
第二个需要牢记于心的重要设计原则是:
"软件组件应该对扩展开放,但对修改关闭"
这个原则意味着我们类应该设计成当后续开发人员需要针对特定的需求改变控制流程时,他们需要做的仅仅是扩展现有的类,然后重写类的一些函数。
如果其他的开发人员由于现有类的一些约束而无法设计所需要的行为,那么我们就需要考虑修改现有的类。这并不意味着任何人都可以修改现有类的逻辑,但软件应该允许其他的开发人员能够通过一些无害的方式重写类的方法。
例如:如果我们深入研究一些优秀的框架,如:struts,spring,我们会发现,我们不能修改这些框架的核心逻辑和请求处理过程,但我们通过在配置文件中扩展一些类型或插件来实现或修改所需要的应用流程。
3. 里氏替换原则(Liskov’s Substitution Principle)
里氏替换原则是开闭原则的一个变种:
"衍生类可以完全替换其基类"
该原则意味着后续开发人员扩展的类型可以无缝地插入到现有的应用中。也就是说,如果一个后续开发人员扩展了现有类型的一部分并注入到框架/应用中,尽管其扩展类编写的并不好,但应用也不能中断,或抛出致命的异常。
上述的要求可以通过严格遵守单一责任原则来保证。如果我们的基类均只承担单一的责任,最坏的情况也就是后续开发人员的重写只导致一个功能出错,而不会导致整个应用出错。
4.接口隔离原则(Interface Segregation Principle)
这个原则是笔者最喜欢的原则。它适用作为限制类的单一责任的界面:
"客户端不应该被强迫去实现其不需要使用的方法"
例如:开发人员Alex创建了一个接口Reportable
,并添加了两个方法generateExcel()
和generatedPdf()
。现在,客户端A需要使用这个接口,但客户端A只需要使用PDF格式的报告(Report),不需要Excel格式。客户端A能够轻松地达到目标吗?
当然不行。客户端A将不得不实现两个方法,不管其是否实现另一个方法,或者仅仅是一个空方法,都是系统额外的负担。这不是我们想要的。
那么,解决什么是解决方案?答案是将现有的一个接口拆分成两个接口,即 PdfReportable
和ExcelReportable
。这样可能让客户端拥有足够的弹性去选择需要的方法。
5.依赖反转原则(Dependency Inversion Principle)
我们对这个原则名字里面的词都很熟悉:
"依赖抽象,而不是依赖具体"
也就是说,在设计我们的软件时,各个模型应该互相独立,再使用一个抽象层将它们整合在一起。经典的案例就是spring framework中使用的BeanFactory。在spring framework中,所有模型都以独立的组件(Components)的形式存在,这些组件通过简单的注入形成依赖,并一起工作。这些组件有着明显的边界,因此,我们也可以直接在其他非spring环境下使用。
这些都是通过依赖反转和开闭原则实现的。所有的模型仅暴露其抽象,这对扩展功能或以插件形式构建系统很有用。
相关文章
- 暂无相关文章
用户点评