设计模式的重要性和应用: 软件设计中普遍反复出现的问题的解决方案; 面向对象 -->功能模块(设计模式+算法(数据结构)) -- > 框架 --> 架构(服务器集群)
设计模型的七大设计原则
1- 单一职责Single Responsibility : 一个类只负责一项职责; 只有逻辑足够简单,类中方法数量足够少,才可以在方法级别保持单一职责原则; 降低变更的风险;
2- 接口隔离Interface Segragation: 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖(使用)应该建立在最小接口上。
ISP - A 类依赖B类实现接口的1,2,3方法;C类依赖D类实现接口1,4,5方法
3 - 依赖倒转Dependence Inversion: 实现类依赖抽象
- 高层模块不应该依赖低层,二者都应该抽象(即高层模块,低层模块各自都应该依赖抽象类、接口;或低层模块尽量抽象);
- 抽象不应该依赖细节,细节应该依赖抽象;(抽象的东西相对稳定,细节多变)(变量的声明尽量时抽象类和接口)
- 面向接口编程;(当继承时要遵循里氏替换原则)
- 使用接口或抽象类目的是制定规范,不涉及任何细节的操作,由实现类实现细节
========================代码示例===========================
Class A 高层模块
Class B1 implements Interface B{ @override funcB(){} }
Class B2 implements Interface B{ @override funcB(){} }
依赖关系传递的三种方式:*****
(依赖关系)接口传递;高层class A{ void funcA(B b){ b.funcB(); } }
调用 :A a = new A(); a.funcA(new B1() );
(组合关系)构造方法传递;class A{ private B b; A(B b){this.b = b} void funcA(){this.b.funcB()} }
调用: A a = new A(new B1()); a.funcA();
(聚合关系)setter方式传递;class A{ private B b; void setB(B b){this.b = b}; void funcA(){this.b.funcB() }
调用:A a = new A(); a.setB(new B2()); a.funcA();
================================代码示例=======================
4 - 里氏替换: 正确使用继承的原则
- 引用基类的地方可以透明的使用子类;
- 子类中尽量不要重写父类的方法(将公用相同的方法提升到基类Base,避免方法重写);
- 继承实际上让类的耦合性增强了,可以通过聚合,组合,依赖 来解决问题(如图)
- 子类中尽量不要重写父类的方法(将公用相同的方法提升到基类Base,避免方法重写);
5- 开闭原则OCP: 对提供方扩展开放,对使用方修改关闭(使用设计模式的目的); 用抽象构建框架,用实现扩展细节;
当软件新增功能时,尽量扩展代码而不是修改代码
6 - 迪米特法原则Demeter principle:
- 一个对象应该对其他对象保持最少的了解,最少知道原则;
- 减少类的耦合度;
- 只与直接的朋友通信(出现在成员变量,方法参数,方法返回值中的类是直接朋友;最好不要以局部变量的形式出现在类的内部);
-
- 对于被依赖的类,尽量将逻辑封装在类的内部,对外除了提供public方法,不对外泄露任何信息
- 减少类的耦合度;
7 - 合成复用原则(*): 尽量使用合依赖、组合、聚合的方式,而不是使用继承
UML 图 简单概括:
1. 分类
- 用例图
- 静态结构图:类图,包图,组件图,部署图
- 动态行为图:交互图(时序图与协作图),状态图,活动图
2.关于UML 类图:
组件: 类
属性名:数据类型
方法名(参数名:参数数据类型):返回值类型
类图设计原则(依赖,关联,泛化(继承),实现,聚合,组合)
- 依赖:在类中使用了另一个类,如果另一个类不存在则编译不通过;(使用者指向被使用者)
- 泛化/实现:是依赖关系的特例(子类指向父类,实现类指向被实现类)
- 关联:是依赖关系特例; 多重性:单向一对一;双向一对一
- 聚合:是关联关系的特例;使用者直线头连着被使用者; 整体和部分是可以分开的(成员属性);多重性:单聚合/多重聚合
- 组合:整体和成员不可分离;使用者直线头连着被使用者;成员变量和整体一起创建销毁;级联删除只对组合关系有效,对聚合关系无效