Java 设计模式
设计模式是什么
设计模式,简单来说就前人编程总结出来的套路
为什么要学习设计模式
适应变化,提高代码复用率。改善系统的设计,增强系统的健壮性、可扩展性,为以后需求修改作铺垫.
设计模式的六个基本原则
单一职责
官方解释:应该有且仅有一个原因引起类的变更。简单点说,一个类,最好只负责一件事,只有一个引起它变化的原因。
通俗来说就是一个类只负责一项职责;譬如一个学生类,那么它就应该只包含学生相关的属性和操作而不会包含其他身份的属性和操作;但是想要每个类都做到单一职责在实际当中,就会增加实体类的数量,但是这是必然的,因为很多时候不管做人还是做事都是不可以两全其美的
在OOP里面,高内聚、低耦合是软件设计追求的目标,而单一职责原则可以看做是高内聚、低耦合的引申,将职责定义为引起变化的原因,以提高内聚性,以此来减少引起变化的原因。职责过多,可能引起变化的原因就越多,这将是导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责通常意味着单一的功能,因此不要为类实现过多的功能点,以保证实体只有一个引起它变化的原因。
里氏替换
官方解释:所有引用基类(父类)的地方必须能透明地使用其子类的对象。原则:子类可以扩展父类的功能,但不能改变父类原有的功能。
父类能出现的地方都可以用子类来代替,而且换成子类也不会出现任何错误或异常,而使用者也无需知道是父类还是子类,但反过来则不成立。总之,就是抽象。
子类必须完全实现父类的抽象方法,但不能覆盖父类的非抽象方法;
- 子类中可以增加自己特有的方法;
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数要更宽松;
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
优点:
提高代码的重用性,子类拥有父类的方法和属性;
提高代码的可扩展性,子类可形似于父类,但异于父类,保留自我的特性;
缺点:
继承是侵入性的,只要继承就必须拥有父类的所有方法和属性,在一定程度上约束了子类,降低了代码的灵活性;
增加了耦合,当父类的常量、变量或者方法被修改了,需要考虑子类的修改,所以一旦父类有了变动,很可能会造成不可预知的错误
依赖倒置
官方解释:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节(实现);细节(实现)应该依赖抽象;
高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。换言之,模块间的依赖是通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。
接口和抽象类不应该依赖于实现类,而实现类依赖接口或抽象类。这一点其实不用多说,很好理解,“面向接口编程”思想正是这点的最好体现。
尽量使用接口来去规范依赖,目的是增大其扩展性;如一个读取数据的类,应该使用接口来规范,因为数据可以通过很多途径获取,如网络,文本,数据库等等
接口隔离(最小化接口原则 或 接口分离原则)
官方解释:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
一个类不该实现它不需要的接口,如类a需实现接口x,而x中有1,2,3这三个方法,而只有1是类a需要的,那么这是就不应该实现接口x;可以用适配器模式解决
迪米特法则(最小知原则)
官方解释:一个软件实体应当尽可能少地与其他实体发生相互作用,如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。
在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
例如:类的功能不要全暴露出去,应该只暴露该类职责的基本功能即可,目的是做到类的高内聚低耦合(我们编写一个类的字段通常会用private修饰,这就是该原则的体现)
如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。
开闭原则
官方解释:软件实体(包括类、模块、功能等)应该对扩展开放,但是对修改关闭
简单理解就是,如有个线上的系统中有个功能类A,现在需要扩展该类的功能,这时正确的做法不是修改类A的源码,而是使用其他扩展的方式来去完成功能的扩展,目录是避免修改源码带来的隐患。Spring中的AOP就很好的实现的这个原则
常用的设计模式以及对应基本原则
todo