设计模式的重要性
- 以实际工作举例: 给用户开,开发完成后客户增加新的功能,例如原本程序适配两个产品,增加第三个产品(程序可扩展性)
- 程序开发完成后的后续维护(规范性,可读性)
- 总结: 高内聚,低耦合,可维护性,可扩展性,
类与类之间的关系
- 依赖: 类A中用到了类B 则为依赖关系(类B在类中以成员变量,方法形参,方法返回值存在,或在方法中使用到了)
- 泛化: 继承关系,特殊的依赖
- 实现: 实现接口关系,特殊的依赖
- 关联: 又分为单向,多向,一对一,一对多,多对多等,例如类A在类B中一属性存在,类B中没有类A,则为单向,类A又是类B的属性则是多向,若属性是一个集合等则是一对多,例如学生与老师则是多对多
- 聚合与组合关系: 特殊的关联关系, 例如类A是类B的属性,在类B中new创建出来,随着类B的消失而消失,类B与类A则是组合关系,如果类A在类B中不会随着类B的消失而消失则可以看为是聚合关系,具体要看在哪个角度去区分,如果在Persion里面的id是属性,不是通过new创建的,删除了这个Persion,这个id存在也就没什么意义了
设计模式的七大原则
- 单一职责原则: 一个类负责一项职责,例如xxxDao,只是xxx表对应的类,降低代码复杂度,提高类的可读性,可维护性,降低修改带来的风险(类级别,方法级别,代码级别)
- 接口隔离原则: 框架工作中,创建接口,创建接口实现类,编写方法,假设有其他类需要用到这个方 法,将接口注入到这个类中,通过接口去调用,将接口拆分,创建不同的类,去实现指定的接口,而不是将所有方法写在同一个接口中,其它类去实现这个接口需要重写用不到的方法
- 依赖倒转原则: 面向接口编程, 细节依赖抽象, 功能模块尽量使用抽象类或接口,通过该类的接口或抽象类注入,调用,利于程序的扩展(假设某个功能需要更改时,只需要更改其实现方法,或重写实现类继续继承这个接口,其调用方可以不用更改),依赖传递的三种方式: 接口传递(接口A中有抽象方法,该方法的形参为类B,类C实现接口A,并重写抽象方法,此时类C中就可以使用类B)构造器传递(A类需要使用B类, “new A(B b)” ), setter方法传递
- 里氏替换原则: 子类 extends 父类, 在带来便利的同时也存在弊端,例如重写父类方法会增加代码的耦合度,修改父类的方法时必须考虑对子类的影响,进而提出了里氏替换原则,也就是子类尽量不要重写父类方法,类A需要使用类B,或者重写类B中的方法,此时可以创建一个公共的base接口,A与B作为同级别的存在,通过聚合,组合,依赖来解决继承父类重写父类方法出现的问题, 就可以减少代码耦合
- 开闭原则ocp(核心): 提供方而言扩展开放, 调用方而言修改关闭, 假设或增加新的需求,对提供该功能的方法进行扩展,例如增加条件判断等,不修改原的调用方? 创建公共的抽象类或接口,原有功能与新功能继承这个公共的抽象,根据需求进行各自的实现,调用方通过接口进行调用,不用修改
- 迪米特法则: 最少知道原则,至于直接朋友通信,什么是直接朋友: 假设类A在类B中以成员变量,方法形参,方法返回值的形式进行引用,那么类A与类B为朋友关系,在类B的方法体中通过new创建出类B的实例,这种可以成为陌生关系,尽量避免陌生关系,在自己的类中完成自己的工作,降低类与类的耦合关系
- 合成复用原则 : 尽量使用合成,聚合的方式而不是继承的方式,假设类A使用类B的方法,不要用类A去继承类B,方式一: 类B作为类A的方法形参,在类A的方法中通过形参调用,方式二: 类B作为类A的属性,通过属性调用;方式三: 类A提供一个带参构造,类B作为类A的构造器参数,在实例化类A时传递一个类B
总结设计原则的核心: 面向接口编程,高内聚低耦合,可能变化的业务代码与功能代码进行剥离
设计模式的分类
- 创建型模式: 关注与对象的创建, 单例模式, 抽象工厂模式, 原型模式, 建造者模式, 工厂模式
- 结构型模式: 关注与软件结构,软件的伸缩性,扩展性, 适配器模式, 桥接模式, 装饰模式, 组合模式, 外观模式, 享元模式, 代理模式
- 行为型模式: 关注与方法行为, 模板方法模式, 命令模式, 访问者模式, 迭代器模式, 观察者模式, 中介者模式,备忘录模式, 解释器模式, 状态模式, 策略模式, 责任链模式
设计模式的学习步骤
1.分析传统功能实现(不考虑设计模式的情况下) 与使用xxx设计模式的区别
2. xxx设计模式是什么,解决了什么问题,优缺点
3. 分析xxx设计模式中各个不同角色的作用
4. 在框架中(Spring),哪里使用到了该设计模式,源码分析