UML图
http://www.360doc.com/content/13/0304/13/10504424_269223190.shtml
http://blog.csdn.net/wishchin/article/details/46771761
http://jingyan.baidu.com/article/c85b7a646123b3003bac9584.html
http://www.jianshu.com/p/884fa91ba7f0
http://www.jianshu.com/p/986c46d11d9e
一、单一职责
单一职责原则,英文Single Reponsobility Principle 缩写SRP
一个备受争议却又及其重要的原则。因为单一职责的划分界限并不总是那么清晰,很多时候需要靠个人经验来界定。
最大的问题是对职责的定义,什么是类的职责,以及怎么划分类的职责。
面向对象设计,--必须考虑到 可扩展性,灵活性,稳定性。
所有的功能都写在一个类里,随着功能的增多,类会越来越大,代码会越来越复杂,系统会越来越脆弱
imageload例子
如何划分一个类,一个函数的职责,每个人都有自己的想法,需要根据个人经验,具体的业务逻辑而定。
一些基本的原则:两个完全不一样的功能就不应该放在一个类中,一个类中应该是一组相关性很高的函数、数据的封装。
不断的审视代码,根据具体的业务、功能对类进行相应的划分。
二、开闭原则--让程序更稳定、更灵活
功能提取成接口
开闭原则的英文全称 Open Close Principle 缩写OCP,
它是Java世界最基础的设计原则,它知道如何建立一个稳定的、灵活的系统。
开闭的原则:软件中的对象(类,模块,函数)应该,对于修改是关闭的。
当软件需要变化时,我们应该尽可能通过扩展的方式来实现变化,而不是通过修改已有代码。但是在实际开发中,修改原代码、扩展代码往往是同时存在的。
分析
每次在程序中加入新的缓存实例都需要修改imageloader类,然后通过一个布尔变量来让用户选择使用哪种缓存,因此,就使得imageloader类存在各种ifelse判断语句*,通过这些判断来确定使用哪种缓存。随着这些逻辑的引入,代码变得越来越复杂、脆弱,如果一不小心写错了某个if条件,那就需要更多的时间来排除,整个imageloader类也会越来越变得臃肿,可扩展性差。
提取成一个图片缓存的接口,用来抽象图片的缓存功能
imageloader类增加了一个setImageCache(ImageCache cache)函数,用户也可以通过该函数设置缓存实现,也就是通常说的依赖注入
当用户需要自定义实现缓存策略,只需要新建一个实现imageCache接口的类,然后构造该类的对象并通过setImageCache(ImageCache cache)注入到imageloader中,这样imageloader就实现了千变万化的缓存策略, 且扩展这些缓存策略不会导致imageloader类的修改。
当然应该尽量这样做,以便代码恢复到正常的“进化”,而不是通过继承等方式添加新的实现,这会导致类型的膨胀以及历史遗留代码的冗余。
三、里氏替换原则--扩展性更好的系统
英文全Liskov Substitution Principle 缩写是LSP
定义
所有引用基类的地方必须能透明地使用其子类对象。
我们知道,面向对象的语言三大特点是继承,封装,多态,里氏替换原则就是依赖继承,多态这两大特性。通俗点讲:只要父类能出现的地方子类就可以出现,而且替换为子类也不会出现任何错误或异常,使用者根本不需要知道是父类还是子类。
例子
window依赖于View,而View定义了一个视图抽象,子类通过继承View的draw方法实现具有各自特色的功能,在这里就是绘制自身内容。任何继承自View的子类都可以传递给show函数,就是所谓的里氏替换。通过里氏替换,就可以自定义各式各样、千变万化的view,然后传递给window,window负责组织view,并将view展示到屏幕上。
里氏替换原则的核心思想是抽象,抽象又依赖了继承这个特性,
OOP当中,继承的优缺点都相当明显
优点
(1)代码重用,减少创建类的成本,每个子类都拥有父类的方法和属性;
(2)子类与父类基本相似,但又与父类有所区别。
(3)提高代码的可扩展性。
缺点
(1)继承是侵入性的,只要继承就必须拥有父类所有的属性和方法。
(2)可能造成子类代码冗余、灵活性降低,因为子类必须拥有父类的属性和方法。
事物总是有两面性的,如何权衡利弊都是根据实际情况来做出选择并加以处理。里氏替换原则指导我们构建扩展性更好的软件系统。
开闭原则和里氏替换原则往往是生死相依的、不离不弃的,通过里氏替换来达到对外扩展,对修改关闭的效果。然而,这两个原则都同时强调--抽象,因此,开发过程中运用抽象是走向代码优化的重要一步
四、依赖倒置原则--让项目拥有变化得能力
全英文是:Dependence Inversion Priciple,缩写是DIP。依赖倒置原则指代了一种特定的解耦形式,
依赖倒置原则有以下几个关键点:
(1)高层模块不应该依赖低层模块,两者都应该依赖起抽象。
(2)抽象不应该依赖细节。
(3)细节应该依赖抽象。
在java语言中
抽象:就是指接口或抽象类,两者都不能直接被实例化的
细节:就是实现类,实现接口或者继承抽象类而产生的类就是细节,其特点就是可以被直接实例化。
高层模块:就是调用端
低层模块:就是具体实现类
依赖倒置原则
模块间的依赖是通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
----面向接口编程----面向抽象编程。
面向接口编程是面向对象编程的精髓之一
当类与类直接依赖细节,那他们之间就有直接的耦合,当具体实现需要变化时,意味着需要修改依赖者的代码,这限制了系统的可扩展性。
案例
五、接口隔离原则----系统有更高的灵活性
全英文InterfaceSegregasion Principles,缩写是ISP。
定义:客户端不应该依赖它不需要的接口。
另一个定义:类间的依赖关系应该建立在最小的接口上。
接口隔离原则将非常庞大、臃肿的接口拆分成更小和更具体的接口,这样客户只需要知道他们感兴趣的方法。
接口隔离原则的目的是系统解开耦合,从而容易重构、更改和重新部署。
案例
java中有一个类Closeable接口,该接口表示了一个可关闭的对象,它只有一个close方法
CloseUtils的closeQuietly方法的基本原理是依赖于Closeable抽象而不是具体实现(依赖倒置原则),并且建立在最小化依赖原则的基础上,它只需要知道这个对象是可关闭的,其它的一概不关心,也就是这里的接口隔离原则。
六、迪米特原则----更好的可扩展性
参考
《Android源码设计模式解析与实战 第二版》强烈建议拜读
https://juejin.im/entry/5833a33c61ff4b006c24daa3