【Java程序员应当知道的10个面向对象设计原则】

面向对象设计原则是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心, 但我见过的大多数Java程序员热心于像Singleton (单例) 、 Decorator(装饰器)、Observer(观察者) 等设计模式,而没有把足够多的注意力放在学习面向对象的分析和设计上面。学习面向对象编程像“抽象”、“封装”、“多态”、“继承” 等基础知识是重要的,但同时为了创建简洁、模块化的设计,了解这些设计原则也同等重要。我经常看到不同经验水平的java程序员,他们有的不知道这些OOPS 和SOLID(PS:请看最后的解释)设计原则,有的只是不知道一个特定的设计原则会带来怎样的益处,甚至不知道在编码中如何使用这些设计原则。

1.(设计原则)

底线是永远追求高内聚、低耦合的编码或设计。 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设计原则需要有文章清楚的介绍它们,在此我一定尽力做到这点,但现在请您准备浏览以下设计模式(原则)。

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 等书也这样建议。(PS:这两本是非常不错的Java好书,推荐入门后学习,有一定难度)

10.代理原则

不要期望一个类完成所有的功能,可以适当地把一些功能交给代理类实现。代理原则的典范是:Java 中的equals() 和 hashCode() 方法。为了比较两个对象的内容是否相同,我们让用于比较的类本身完成对比工作而非它们的调用方。这种设计原则的好处是:没有重复编码而且很容易修改类的行为。

总结

以上所有面向对象的设计原则可以帮助您写出灵活、优雅的代码:具有高内聚低耦合的代码结构。理论只是第一步,更重要的是我们要习得一种能力去发现什么时候使用这些设计原则。去发现我们是否违反了什么设计原则和影响了代码的灵活性,但是世界上没有什么是完美的,我们解决问题时不能总去使用设计模式和设计原则,它们大多用于有较长维护周期的大型企业项目。

首先解释一下SOLID:S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则的首字母缩写。

SRP(The Single Responsibility Principle)单一责任原则

OCP(The Open Closed Principle)开放封闭原则

LSP(The Liskov Substitution Principle)里氏替换原则

DIP(The Dependency Inversion Principle)依赖倒置原则

ISP(The Interface Segregation Principle)接口分离原则

这些OO原则可以说是面向对象编程的精髓所在,好比易筋经之心法,想要运用自如,需要长时间的编码积累体会,着急不得。但又要避免滥用,由其是在JavaEE开发和Android开发中,要以实际项目需求出发,不过,一切原则以扩展性和性能来权衡考虑,总是不会错的。


-注明:【本文摘自同行说应用,更多干货可下载同行说app】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容