面向对象设计原则是OOPS编程的核心, 但我见过的大多数Java程序员热心于像Singleton (单例) 、 Decorator(装饰器)、Observer(观察者)等设计模式, 而没有把足够多的注意力放在学习面向对象的分析和设计上面。学习面向对象编程像“抽象”、“封装”、“多态”、“继承” 等基础知识是重要的,但同时为了创建简洁、模块化的设计,了解这些设计原则也同等重要。我经常看到不同经验水平的java程序员,他们有的不知道这些 OOPS 和SOLID设计原则,有的只是不知道一个特定的设计原则会带来怎样的益处,甚至不知道在编码中如何使用这些设计原则。
(设 计原则)底线是永远追求高内聚、低耦合的编码或设计。 Apache 和 Sun的开源代码是学习Java和OOPS设计原则的良好范例。它们向我们展示了,设计原则在Java编程中是如何使用的。Java JDK 使用了一些设计原则:BorderFactory类中的工厂模式、Runtime类中的单例模式、java.io 类中的装饰器模式。顺便说一句,如果您真的对Java编码原则感兴趣,请阅读Joshua Bloch 的Effective Java,他编写过Java API。我个人最喜欢的关于面向对象设计模式的是Kathy Sierra的Head First Design Pattern(深入浅出设计模式),以及其它的关于深入浅出面向对象分析和设计。这些书对编写更好的代码有很大帮助,充分利用各种面向对象和SOLID 的设计模式。
虽然学习设计模式(原则)最好的方法是现实中的例子和理解违反设计原则带来的不便,本文的宗旨是向那些没有接触过或正处于学习阶段的Java程序员介绍面向对象设计原则。我个人认为OOPS 和SOLID设计原则需要有文章清楚的介绍它们,在此我一定尽力做到这点,但现在请您准备浏览以下设计模式(原则) :)
1)DRY (Don't repeat yourself)
我们第一个面向对象设计原则是:DRY ,从名称可以看出DRY(don't repeat yourself)意 思是不写重复代码,而是抽象成可复用的代码块。如果您有两处以上相同的代码块,请考虑把它们抽象成一个单独的方法;或者您多次使用了硬编码的值,请把它们 设置成公共常量。这种面向对象设计原则的优点是易于维护。重要的是不要滥用此原则,重复不是针对代码而是针对功能来说。它的意思是,如果您使用通用代码来验证OrderID和SSN,这并不意味着它们是相同的或者他们今后将保持不变。通过把通用代码用于实现两种不同的功能,或者您把这两种不同的功能密切地联系在一起;当您的OrderID格式改变时,您的SSN验证代码将会中断。所以要当心这种耦合,而且不要把彼此之间没有任何关系却类似的代码组合在一起。
2)、封装经常修改的代码(Encapsulate What Changes)
在软件领域永远不变的是“变化”,所以把您认为或怀疑将来要被修改的代码封装起来。这种面向对象设计模式的优点是:易于测试和维护恰当封装的代码。如果您在用Java编程,那么请遵守以下原则:变量和方法的访问权限默认设置为私有,并且逐步放开它们的访问权限,例如从“private”到“protected ”、“not public”。Java中的一些设计模式使用了封装,工厂设计模式就是一个例子,它封装了创建对象的代码而且提供了以下灵活性:后续生成新对象不影响现有的代码。
3)、打开/关闭设计原则(OpenClosed Design Principle)
类、方法/函数应当是对扩展(新功能)开放,对修改闭合。这是另外一个优雅的SOLID 设计原则,以防止有人修改通过测试的代码。理想情况下假如您添加了新功能,那么您的代码要经过测试,这就是打开/关闭设计原则的目标。顺便说一句,SOLID中的字母“O”指的是打开/关闭设计原则。
4)、单一职责原则Single Responsibility Principle(SRP)
单一职责原则是另外一个SOLID 设计原则,SOLID中的字母“S”指的就是它。按照SRP,一个类修改的原因应当有且只有一个,或者一个类应当总是实现单一功能。如果您在Java中的 一个类实现了多个功能,那么这些功能之间便产生了耦合关系;如果您修改其中的一个功能,您有可能就打破了这种耦合关系,那么就要进行另一轮测试以避免产生 新的问题。
5)、依赖注入/反转原则(Dependency Injection or Inversion principle)
不要问框架的依赖注入功能将会给你带来什么益处,依赖注入功能在spring框架里已经很好的得到了实现,这一设计原则的优雅之处在于:DI框架注入的任何一个类都易于用模拟对象进行测试,并且更易于维护,因为创建对象的代码在框架里是集中的而且和客户端代码是隔离的。有多种方法可以实现依赖注入,例如使用字节码工具,其中一些AOP(面向切面编程)框架如切入点表达式或者spring里使用的代理。想对这种SOLID设计原则了解更多,请看IOC 和 DI设计模式中的例子。 SOLID中的字母“D”指的就是这种设计原则。
6)、优先使用组合而非继承(Favor Composition over Inheritance)
如果可以的话,要优先使用组合而非继承。你们中的一些人可能为此争论,但我发现组合比继承更有灵活性。组合允许在运行时通过设置属性修改一个类的行为,通过使用多态即以接口的形式实现类之间的组合关系,并且为修改组合关系提供了灵活性。甚至 Effective Java也建议优先使用组合而非继承。
7)、里氏替换原则(Liskov Substitution Principle LSP)
根据里氏替换原则,父类出现的地方可以用子类来替换,例如父类的方法或函数被子类对象替换应该没有任何问题。LSP和单一职责原则、接口隔离原则密切相关。如果一个父类的功能比其子类还要多,那么它可能不支持这一功能,而且也违反了LSP设计原则。为了遵循 LSP SOLID设计原则,派生类或子类(相对父类比较)必须增强功能,而非减少。SOLID中的字母“L”指的就是 LSP设计原则。
8)、接口隔离原则
接口隔离原则指,如果不需要一个接口的功能,那么就不要实现此接口。这大多在以下情况发生:一个接口包含多种功能,而实现类只需要其中一种功能。接口设计是一种棘手的工作,因为一旦发布了接口,您就不能修改它否则会影响实现该接口的类。在Java中这种设计原则的另一个好处是:接口有一个特点,任何类使用它之前都要实现该接口所有的方法,所以使用功能单一的接口意味着实现更少的方法。
9)、编程以接口(而非实现对象)为中心
编程总是以接口(而非实现对象)为中心,这会使代码的结构灵活,而且任何一个新的接口实现对象都能兼容现有代码结构。所以在Java中,变量、方法返回值、方法参数的数据类型请使用接口。这是许多Java程序员的建议, Effective Java 以及 head first design pattern 等书也这样建议。
10)、代理原则
不要期望一个类完成所有的功能,可以适当地把一些功能交给代理类实现。代理原则的典范是:Java 中的equals() 和 hashCode() 方法。为了比较两个对象的内容是否相同,我们让用于比较的类本身完成对比工作而非它们的调用方。这种设计原则的好处是:没有重复编码而且很容易修改类的行为。
总结
以 上所有面向对象的设计原则可以帮助您写出灵活、优雅的代码:具有高内聚低耦合的代码结构。理论只是第一步,更重要的是我们要习得一种能力去发现什么时候使 用这些设计原则。去发现我们是否违反了什么设计原则和影响了代码的灵活性,但是世界上没有什么是完美的,我们解决问题时不能总去使用设计模式和设计原则, 它们大多用于有较长维护周期的大型企业项目。
1. 本文由程序员学架构翻译
2. 本文译自
http://javarevisited.blogspot.com/2012/03/10-object-oriented-design-p
3. 转载请务必注明本文出自:程序员学架构(微信号:archleaner)
4. 更多文章请扫码:
相关推荐
以下是10个Java程序员应当熟悉的面向对象设计原则: 1. **DRY原则**(Don't Repeat Yourself):避免重复的代码,将通用功能抽象成可重用的模块。这样做的好处是提高代码的维护性,但要注意避免过度抽象导致不必要...
面向对象设计原则是编程实践中的一种核心思想,尤其在OOPS(面向对象的程序设计系统)中,它们指导我们编写可维护、可扩展和高效的代码。本文将深入探讨这些原则,帮助程序员理解并应用它们。 首先,让我们从第一条...
除了以上技能之外,Java程序员还应当具备一定的广度知识。例如,了解J2EE框架、数据库管理、中间件部署、前端技术栈等,这对于成为一名全栈开发者非常有帮助。 总之,成为一名优秀的Java程序员并非一朝一夕之事,...
封装(Encapsulation)是面向对象程序设计的一个原则,它指的是将数据(属性)和行为(方法)捆绑在一起,形成一个独立的单元,并通过对外提供的接口与外界进行交互。封装的目的是隐藏对象的内部状态,只能通过指定...
### 知识点总结 #### 一、软件工程生命周期 ...以上内容涵盖了软件工程生命周期的各个阶段、设计模式的主要原则以及面向对象的基本概念。希望这些知识点能够帮助您更好地理解和掌握软件开发的基础理论和技术实践。
首先,作为一本面试宝典,本书应当覆盖Java的核心概念,如Java语言的基础语法、面向对象的编程原则、集合框架、异常处理、IO流、多线程以及网络编程等。对于这些知识点,书本可能会提供面试中常见的问题类型,以及...
面向对象设计原则 - **单一职责原则**:一个类应该只有一个引起它变化的原因。 - **开放封闭原则**:软件实体应该是可扩展的,而无需修改。 - **里氏替换原则**:子类可以替换父类并且程序的行为不会受到影响。 - ...
该资源涵盖了软件设计模式的基础知识,包括软件设计模式的概述、UML中的类图、面向对象的设计原则、单例模式、原型模式等。 软件设计模式概述 软件设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码...
1. **扎实的编程基础**:Java程序员应当展示他们对Java核心概念的深入理解,例如面向对象编程(OOP)原则、类与对象、异常处理、多线程、集合框架等。这表明他们具有良好的编程风格和实践能力。 2. **Web开发经验**...
Java设计原则是面向对象编程中的核心思想,它们指导开发者创建可维护、可扩展且易于理解的软件系统。本文将深入探讨这些原则,并提供如何在实际项目中应用它们的见解。 首先,我们来看单一职责原则(Single ...
每种图表都有其特定的使用场景和设计目的,Java程序员应当根据具体情况选择合适的图表类型。 第二章“使用图(Diagrams)”讨论了为什么需要使用模型和建模,以及为什么在编码前需要构造一个全面的设计。UML不仅是一...
这些原则不仅适用于Java,也适用于其他面向对象编程语言。以下是对这六大设计原则的详细解释: 1. 单一职责原则(Single Responsibility Principle, SRP): 这个原则规定,一个类或模块应该有且只有一个职责,即...
Java面向对象编程是一种核心的编程范式,它基于“万物皆对象”的理念,将现实世界中的实体抽象为类,然后通过类来创建和操作对象。在这个PPT教案中,主要讲解了以下几个关键知识点: 1. **方法**:方法是类中的功能...
Closed Principle(开闭原则)、Single Responsibility Principle(单一职责原则)、Liskov Substitution Principle(里氏替换原则)、... Inversion Principle(依赖倒置原则)是面向对象设计的五个基本原则...
设计模式不仅仅是面向对象设计的基本技巧,也是提高代码复用性、增强系统的可维护性和可扩展性的关键技术。书中内容涵盖了从基本的设计原则到具体的模式实现,提供了丰富的实例来辅助理解。 1. 设计模式的分类:...
1. **Java基础**:Java的基础语法是任何Java程序员必须掌握的,包括类、对象、接口、继承、多态等面向对象的概念。此外,异常处理、集合框架(如List、Set、Map)和IO流也是Java编程中的核心知识点。 2. **Java设计...