设计模式--面向对象编程的六大设计原则

开篇

新工作主要是做android系统应用层的开发维护, 所以阅读大量源代码就是日常了,阅读过程中,深深的感受到了有必要再复习一遍设计模式,以便于吸收Google那庞大的精华~

也越来越觉得做好学习笔记是一件很重要的事情,把学了的东西写成博客来记录,也是一件很有趣的事情,这篇就是接下来学习设计模式的第一篇笔记。

面向对象编程的六大设计原则(SOLID)

面向对象编程的六大设计原则有:单一职责原则、开放封闭原则、里氏替换原则、依赖倒转原则、接口隔离原则、迪米特法则,下面将一一介绍。

单一职责原则(SPR:Single Responsibility Principle)

单一职责原则:就一个类而言,应该仅有一个引起它变化的原因, 或者说一个类只负责一个功能领域中的相应职责。

比如我们常用的ListView来展示数据, Listview负责显示, Adapter用来加载数据, 各自负责各自的功能, 以达到高内聚、低耦合的代码结构。

总之,一个类不能有太多的功能, 否则就需要考虑将这个类得多重职能一一拆解。这是最简单但又最难运用的原则,需要有较强的分析设计能力和相关实践经验。

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

开放封闭原则,是指软件实体(类、模块、函数等)应该可以扩展,但是不可修改。大白话就是尽量在不修改原有代码下去进行扩展。

作为开发者,我们深知需求都是会随着时间推移而变化的, 而面对新的需求, 我们又要保证系统的设计架构是稳定的,不能为了一个需求就把以前的架构推翻重来, 那样的话,成本就太大了。

抽象化是开放封闭原则的关键, 所以, 我们在设计代码的时候,要充分考虑,哪些是不易变的, 哪些是很可能变化的,然后将变化的部分通过抽象来隔离变化,从而实现无须对抽象层进行修改,只需要在具体类在抽象中去实现新的功能即可。我们可以通过抽象类或者某个抽象方法,让变化的部分在子类去实现,以达到子类的不同需求。

实际开发中,有些代码在编写时,我们也不知道未来会不会变化, 我们只有通过经验猜测,或者当遇到需要变化的情况是, 这是就需要去创建抽象来隔离以后类似的变化了。

比如,刚开始时, 我们只会做加法运算, 我们就写了一个加法类, 但是后来,我们又学会了减法、乘法、除法等,这时,我们就可以抽象为一个运算类,里面有一个运算的方法, 但是具体怎么运算,就交给子类去具体实现, 从而达到了开放封闭原则。即抽象的运算类就不用去修改,达到了封闭的原则,而运算方法的具体实现就交给子类, 达到了开放的原则。

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

里氏替换原则:子类必须能替换它的父类。即所有引用父类的地方,都可以用一个子类把这个父类替换掉。

例如:List List = new ArrayList();
用子类替换父类即: ArrayList list = new ArrayList();

里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
接口隔离原则(ISP:Interface Segeration Principle)

接口隔离原则:使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些它不需要的接口,应该使接口尽量细化而不过于臃肿。

应当为业务提供尽可能小的单独的接口,而不要提供大的总接口。在面向对象编程语言中,实现一个接口就需要实现该接口中定义的所有方法,因此大的总接口使用起来不一定很方便,为了使接口的职责单一,需要将大接口中的方法根据其职责不同分别放在不同的小接口中,以确保每个接口使用起来都较为方便,并都承担某一单一角色。接口应该尽量细化,同时接口中的方法应该尽量少。

依赖倒转原则(DIP:Dependency Inversion Principle)

依赖倒转原则:抽象不应该依赖细节,细节应该依赖抽象。即要针对接口编程,而不是实现编程。

举个栗子, 做项目多数都要访问数据库,所以整个代码结构中,会包含业务代码和数据库访问, 假如我们需求有变,产品经理或者客户要求使用不同的数据库或者存储信息方式, 如果我们在业务代码和数据库访问代码绑定在一起了, 那就是大灾难,需要修改的代码一大片一大片的。而如果我们将业务代码和数据库访问分为两个模块,分别进行抽象,有自己的抽象父类或借口,那么业务代码调用数据库时, 通过调用数据库的抽象父类或者接口的方法, 则不管底层数据库怎么变化, 业务代码都不用管, 因为抽象父类的方法名不会变,只是具体的实现变了。底层数据库如果发生变化, 我们要做的事就是在一个子类中去具体实现新的数据库即可,不会影响业务代码。

迪米特法则(LoD:Law of Demeter)

迪米特法则,又称为最小知道原则。即一个软件实体应当尽可能少地与其他实体发生相互作用。如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

迪米特法则要求我们在设计系统时,**应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。**简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

下面通过一个简单实例来加深对迪米特法则的理解:

Sunny软件公司所开发CRM系统包含很多业务操作窗口,在这些窗口中,某些界面控件之间存在复杂的交互关系,一个控件事件的触发将导致多个其他界面控件产生响应,例如,当一个按钮(Button)被单击时,对应的列表框(List)、组合框(ComboBox)、文本框(TextBox)、文本标签(Label)等都将发生改变,在初始设计方案中,界面控件之间的交互关系可简化为如下图:

在图1中,由于界面控件之间的交互关系复杂,导致在该窗口中增加新的界面控件时需要修改与之交互的其他控件的源代码,系统扩展性较差,也不便于增加和删除新控件。

现使用迪米特对其进行重构。

在本实例中,可以通过引入一个专门用于控制界面控件交互的中间类(Mediator)来降低界面控件之间的耦合度。引入中间类之后,界面控件之间不再发生直接引用,而是将请求先转发给中间类,再由中间类来完成对其他控件的调用。当需要增加或删除新的控件时,只需修改中间类即可,无须修改新增控件或已有控件的源代码,重构后结构如图2所示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值