- 思维导图
首先分为两部分,规范要求的以及需要根据场景权衡决策的。
- 编码规范
魔鬼数字需要用常量取代,对数据类应该尽量封装。这些是OO基础,无需多言。
- 需要权衡
1、使用值对象还是引用对象
首先这里的值、引用对象,非语言上的值、引用对象,而是从可变、封装性来界定。不可变,完全封装称为值对象,引用对象就是成员可变,未完全封装。
使用引用对象的场景:
- 需要保证唯一性
常见于对象被多个其它类持有,且有修改行为,需要保证唯一性,它们修改的都是同个对象,而不只是name字段都叫XXX的不同实例。这类实现通常用manager进行统一的对象管控。
- 对象池
为了避免重复创建实例造成GC压力,需要对对象进行复用。
对象池的特点,大场景可以切割为多个等大小场景,一次创建,多次复用。但如果是多线程场景,设计较为复杂,就像单例一样,需要慎用。
使用值对象的场景:
- 只读不可变,建议实现时,字段用final前缀,封装完全。
2、用对象替换数组(类封装)
除非面向过程,否则没人会用一个孤立的数组。数组意味着背后的语境或Domain建模.对于OO编程来说,建议就是不要用孤立的数组,先封装。
3、复制被监视的数据(数据的单/双向)
本质就是 数据的双工或者单工
对应实现就是:观察者模式或者事件监听,两者都可以通过接口解耦
- 观察者模式
单工/双工,谁持有谁,还是都相互持有,均为observable实现类
例,数据方向是A->B,那么B实现观察者,A持有B,A中数据发生变化,调用B的update接口,通知B。
数据方向是A<->B,那么A、B均是观察者,AB相互持有,各自数据发生变化,调用对象update接口,通知对方
- 监听事件模式
单攻/双工,谁注册响应谁的事件,还是相互注册响应
例子同观察者
4、单双向引用
- 单向变双向关联
场景:使用很爽,维护很难。适合先构造好,后续只使用.
如果要更新维护,需要确定负责刷新的控制端.
A、B均存在相互调用的场景,且A、B不好作为入参传入,需持有
- 双向变单向关联
场景:不需要A、B均存在相互调用的场景,A、B可以作为入参传入,不需持有。一般外面套个manger,持有A、B两者的集合的设计也可以。
5、集合的封装性
只读场景:集合只能读的场景
可修改场景:封装集合的行为,只能通过接口的增删改来修改集合,封装对象给予的集合对象,均是clone副本.
总结:
这种在linq(java里的steam)场景下,常会见到,经过filter、sort等语句处理生成的集合都是新集合,对其的操作,均不会影响到原集合,保证了原集合的不可变性,如果要做彻底,集合的元对象,也应该做彻底封装,在clone时采用深clone
6、类型码
做枚举用:用枚举或静态类+静态实例对象表示
宿主类部分逻辑,需要依据该类型码做判定:
宿主是有子类:组合方式,变化、差异的部分是什么,提成state、strategy接口,实现类承载,
宿主是无子类:多态方式,变化、差异的部分是什么,父抽象,子实现
7、字段取代子类
差异、变化有限,且内部依赖该字段做的判定逻辑很少或没有(if else),一个或简单几个字段就可以表示,没有必要用多态。