最近在准备面试,看到了这个题目,参考了诸多的博客总结以下。java
S:single Responsibility Principle 单一职责原则面试
一个类只负责一个职责,当且仅当这个职责需求发生变化时,才须要修改这个类。若是有超出这个职责以外的事情,应当从新将职责分离出去。或经过has-a的方式使用新的职责。
单一职责要求一个类只能有一个发生变化的理由,不容许持有超过自身的其余功能,由于若是一个类承担了太多的事情,就会致使抽象体系崩溃,没法知道这个类到底是什么。更重要的是,一旦有一个职责须要修改,就对这个类的其余功能产生影响,这给软件系统带来很大的不稳定性。
在工厂模式中,当工厂试图承担超过自身能力的类的实例化功能时,就必需要修改代码,增长判断或者是其余操做,一旦有需求须要增长,就须要不断增长判断,这一点也违背了开闭原则,所以就须要抽象工厂来对工厂进行抽象。从而分离出具体工厂的职责。下降耦合度。
O open close Principle 开闭原则
一个类或者软件系统,应当是对扩展开放,对修改关闭的。
对于一个类来讲,若是须要修改或者增长新功能,那必须是扩展原有代码,而不是修改原有代码来实现。由于当项目足够大,且多人合做的时候,咱们很难肯定某一个类被多少其余类使用过,也不知道这个类中的方法究竟承担了怎样的职责,若是贸然修改它,将会对软件系统形成不可预知的影响。并且,当有需求频繁变动的时候,咱们也不可能每一次都修改方法,而且评估这个修改对软件系统的影响。若是有修改回退,咱们还要找到以前的代码再改回来。(固然对于这种修改来讲,抽象是一种很是有效的办法。就是增长一个抽象层,抽象层定义行为,而子类去实现具体的逻辑,这个抽象对客户端是透明的,客户端不须要知道怎么实现,是须要使用便可)
对一个软件系统来讲,也是对open close的。好比咱们提供了一个工具类api,api要保证在每个客户机上的功能都是不能被修改的,当须要修改或者增长功能时,就须要api开放一些接口,用于客户机实现具体的定制需求,而这些接口就是一个行为上固定的抽象层。
L 里氏替换原则
在软件领域内,is-a的关系并不必定是现实中的关系,软件内只有当全部子类出现的地方均可以代替为父类而对软件没有影响时,才能说子类与父类有is-a的关系。
这个典型的反例就是:生物学上企鹅是鸟,可是软件系统内,若是要对鸟抽象一个会飞的功能,那么企鹅就不是鸟,由于企鹅不会飞。
java中常常会有父类型的引用指向子类型的对象,这样咱们就能够用统一的父类型,做为抽象层对外的表现,而使用具体的子类实现具体的功能。当须要增长功能时,也只须要增长一个子类,客户端调用的代码甚至都不须要改变。很大程度上实现了代码的复用。对于接口来讲,它只须要约定行为,这样就实现了抽象和解耦。
可是这种特性是须要父类和子类拥有is-a的关系,而不只仅是一个extends关键字。假如在子类型中用了父类型没有的方法,在作里氏替换时就会出错,如此类继承体系就会出问题,既然子类not is a 父类了,
上面说法有问题,以前没有理解清楚。
严格定义:
1.若是对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的全部程序P在全部的对象o1都换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。
2.若是对每个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的全部程序 P 在全部的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
通俗定义:全部引用基类的地方必须能透明地使用其子类的对象。
理解:java中,常常有经过父类型的引用指向子类型的对象,在作抽象层的时候每每也会只操做抽象类或者接口,可是在实际运行的时候,操做的是真正的子类型。也就是说,运行时这个子类型写成父类型是没有问题的。能够在编译期只用父类型。这样咱们在使用中就不须要考虑抽象类和接口到底是怎么实现的,实现了多态。
可是想用这种特性,就必需要符合子类is a 父类,里氏替换原则。表现上就是,子类型不要修改重写父类型已经实现的方法,由于若是这样作,父类型和子类型的行为就会出现误差,从而不能构建is a关系。原本继承是紧耦合的方式,想要使用继承也是处于代码复用了抽象的角度考虑的,那么父类型给定义的办法,必定是一种对子类型都有效的约束,子类型随意篡改父类型的内容是不容许的。也就是说父类型有的子类型也必定要有,且行为同样,子类型能够有本身的办法。好比子类型企鹅若是但愿本身is a 鸟的话,那么必需要实现鸟的fly方法,可是企鹅实际上不会飞,因此,软件层面上考虑,企鹅不能是鸟。
博客说,里氏替换是实现开闭的重要原则,可能指的是,当又须要修改或者增长功能时,能够经过增长一个子类来实现,而软件表现上仍然能够用父类型的对象操做。这就是多态,而想要实现这种便利,就必需要产生is a的关系。
参考资料:
I interface Segregation Principle 接口隔离原则
这个和单一职责有些相似,意思是一个接口表示一个抽象,它的实现类就是子类,子类要拥有单一职责,所以接口也要符合单一职责,固然这里的单一职责并非说只有一个方法。
一个接口不该该有太多的内容,若是子类没有用到其中的某些方法,但仍是须要实例化它们,就会显得多余而容易出错,若是接口方法要发生某种变动,也会致使无关的子类也被影响。既然要重用,那么保证接口粒度足够小,才能被很好的重用。
D dependence Inversion Principle 依赖倒置原则
定义:高层模块不该该依赖于底层模块,两者都应该依赖于抽象,抽象不该该依赖于细节,细节应该依赖于抽象。
其实就是软件分层和抽象的内容,高层模块通常指涉及到具体业务,容易变动的模块,底层模块是指更加底层一点,变化较少,一变化会对许多高层模块产生影响的模块。也就是说
具体的业务要依赖于提供底层服务的模块,而不能本身玩本身的。不管是高层仍是底层,都不该该直接用具体的实现类操做,而须要依赖于抽象,抽象在高层底层和更底层之间架设了一个中间层,架构师抽象这个中间层,提供一个相对稳定的功能,和能够扩展的接口。这样就保证了每一层之间尽可能少地耦合。
开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段