之前总结的时候使用的是word放了很多图在上面,想换成博文的时候发现很多图都没了,于是把word原版放到github上链接如下
https://github.com/1160300611/-
第4-5章 java设计模式的介绍
接口
接口之间可以相互继承 一个类可以实现多个接口 一个接口也可以有多个实现类
接口和实现的类在使用的时候必须知道对应的实现该接口的名称
使用静态工厂方法来返回一个特定类型的值 避免破坏抽象层次
抽象类
抽象方法 一个只有方法的声明的方法 用abstract关键字表示
抽象类 至少包含一个抽象方法的类
接口 只含有抽象方法的抽象类
Override
Rewriteable Methods 可以被重新实现的方法
子类中只能添加新的方法 但是无法重写超类中的方法
Java中不能被重写的方法需要在声明中加入final关键字
Final field 代码初始化之后无法被重新赋值
Final method 防止这个方法被重写
Final class 防止类的继承
重写函数与原函数有一样的函数声明super可以调用父类函数的功能在构造函数中super只能放在第一排
多态 overload
多态的三种类型
1 特殊多态 功能重载
2 参数多态 3 子类型多态,包含多态
也就是说 所有可以用父类型的地方使用子类型一定不会报错
注意 overload 只需要方法名相同而override则需要整个方法的声明都与父类相同
Overloading 多个方法具有相同名字 但有不同的参数列表或者返回值类型
方便用户调用,用户可以用不同的参数列表来调用名称相同但是内涵不同的函数
重载是一个静态的多态 根据参数列表来选择执行的方法,需要进行静态类型检查 在编译阶段决定具体要执行哪种方法
子类重载的函数 父类是可以调用的
泛型
泛型变量 使用< > 来定义的变量
泛型类 定义中包含了泛型变量的类 同理有泛型接口和泛型方法
可以使用多个泛型如Map<E,F>
可以使用通配符?只在使用泛型的时候出现 但不能在定义中出现
编译的时候会被类型变量取代 而且泛型不存在泛型数组
泛型接口有两种实现形式
非泛型的实现 泛型的实现
Public interfaceSet<E> public HashSet<E>imolements Set<E>{
{
} }
子类型多态 B是A的子类型 得到每个A都是B
B的spec至少跟A一样强
子类型多态 不同类型的对象可以统一的处理无需区分
LSP 若S为T的子类,
等价
Equals的自反,传递,对称
等价的三种定义方式
1. 若 AF映射到同样的结果,则等价
2. 若两个对象之间满足自反传递对称的关系,那么为等价关系
3. 站在外部观察者角度发展二者没有区别
4. 站在外部观察者的角度发现二者没有区别
对于ADT来说,“观察”就表示调用该类的运算符
5. 除非对象被修改 否则多次调用该对象得到的结果应该是一样的
6. Hashcode() 返回结果必须一致 相等的对象
7. A.equal(null) 一定返回false
Hashcode 和equals 一起被重写
17 31 法则 这两个比较大的质数
可变观察对象的观察等价性和行为等价性
Object中缺省使用“==”来判断两个对象是否相同
Instanceof操作应该只在equals方法内使用
观察等价性,在不改变状态的情况下,两个mutable对象是否看起来一致
调用observer producer creater 对比两者的状态
行为等价性,调用对象的任意方法,都展现出一致的结果
对于可变对象来说往往倾向于实现严格的观察等价性
有时候观察等价性可能会导致bug
如果某个mutable对象包含在集合类当中当其发生改编后集合类的行为不确定
Collection 使用观察等价性
Stringbuilder 使用行为等价性
对于mutable对象无需重写hashcode()equals()保留缺省值即可
注释的种类
1 title comments
2 introductory comments
3 black comments 4sigle-Line/Tracimg/End-of-line comments
ADT的注释 应当包括
编码规范 怎样正确排序引用的
1 Stabdard packages(java.io) 2third party packages 3 your own packages
可复用型编程
复用的层次 最主要是代码的复用
软件构造过程中任何实体都可能被复用
白盒复用 源代码可见 可修改和扩展 可定制化程度高 需要对内部有充分的了解
黑盒复用 源代码不可见 简单清晰 但是适应性较差
LSP子类型多态 客户端可以用统一的方法处理不同类型的对象
子类型可以增加方法 但是不可以删除方法
子类型要实现抽象类型中所有未实现的方法
子类型中重写的方法必须要求使用同样类型的参数并且返回同样类型的值而且这个重写的方法不能抛出新的异常
更强的不变量 更弱的前置条件 更强的后置条件
协变 父类型->子类型 :越来越具体返回值类型不变或者变得更具体
异常类型不变或者变的更具体
反协变 父类型到子类型 越来越抽象 参数类型不变或者越来越抽象
数组是协变的对于所有T类型的数组 可以接收T的所有子类
如果子类只需要父类中的一小部分方法可以选择不使用继承而使用委派来实现
委派的类型
1 临时性 作为某个方法的参数放到List里面
2 永久性 作为类里面的一个属性或者变量
3 更强的 委派 作为某一部分
Aggregation 将delegation的类放到构造函数中
Comparator 实现该接口意味着该类支持排序
Java中的设计模式
结构设计模式
1. Adapter适配器模式
将某个类/接口转换为用户期望的其他形式 增加一个接口将已经存在的子类封装卡里从而能够隐藏具体子类 通过修改接口让无法合作的类进行合作
2.在抽象类型中可以使用final关键字对共性的方法进行锁定防止之后重写
1.单一责任原则SRP 2开放封闭原则OCP open close
3里氏替换原则LSP 4接口聚合规则 ISP 5依赖注入或倒置原则DIP
高层和底层模块都应该依赖抽象
Creation Patterns
工厂模式 用户不知道要创建哪个类的具体实例
定义一个用来创建具体对象的接口让它的子类来决定实例化哪个类
Build模式
程序的健壮性和正确性
健壮性 输入不正常 仍能表现正常 能运行的程度
处理没有期望到的行为和错误导致的程序中止
即使程序中止,也要向用户准确无歧义的全面展示错误信息
正确性 永不给用户错误的结果
异常
Throwable java中所有的子类都是从throwable中发展出来的子类
Runtime 异常 程序员在编程时的错误导致的
如 数组越界 空指针错误
其他异常: 由外部原因造成的 I/O异常打开一个不存在的文件
Checked 用户可以进行操作属于可预料但不可预防的异常
异常属于spec的一部分 应该写在Post-condition当中
子类不能抛出比父类更广阔的异常 override 协变
父类型没有抛出异常 那么子类也不能抛出异常
断言 Assert 在开发阶段的代码中嵌入检查某些假设是否成立 若成立,表明程序正常 如果断言中的条件不被满足那么会抛出AssertionError
断言可应用于: 内部不变量 表示不变量 控制流不变量 方法的前置条件(检查方法的参数)方法的后置条件(检查方法的返回值)
控制流不变量 若if switch语句没有覆盖所有的可能就用assert语句来覆盖不合法的情况
断言一般在开发阶段帮助我们发现bug 实际运行时一般不再使用
不要在断言中操作数据 执行有副作用的代码
对于pre/post codition 若方法参数来自外部》异常处理
来自自己的其他代码 使用断言
调试 调试的基本过程 重现-定位-修复-反思 常用方法 假设检验法
内存管理
三种内存管理模式 1.静态 2.基于栈的动态 3.基于堆的动态
第一个方式 循环引用清不掉
多线程
线程安全的四种策略
Confinement
将可变数据限制在某个线程内部,避免竞争 不允许任何线程读写该数据
Immutability
不可变数据类型一般都是thread safe的
Synchronized
如果必须使用mutable类型的数据类型共享数据 java提供了decorator模式
Locks and synchronized机制
程序员自己负责多线程之间对于 mutable数据的共享通过同步策略避免多个线程同时访问数据