-
尽可能的让类或者成员不被外接访问
单一职责,高内聚低耦合,降低类被修改的风险;
-
类具有共有的静态finnal数组域 或者返回这种数组域的方法,总是错误的
public class Test { public static final List<String> list=new ArrayList<>(); }
这样的代码容易让外界修改 list中的内容
两种办法- 增加一个共有的不可变列表 复制其中的内容
public class Test {
private static final List<String> list=new ArrayList<>();
public static final List<String> copys= Collections.copy(list,copys);
} - 增加一个公有的方法,返回他的clone;
- 增加一个共有的不可变列表 复制其中的内容
-
在公有类中 我们经常定义一个存储数据的对象
public class Test{ public String a; public String b; }
坚持面向对象的思想 应该给与封装get set方法
以便于后期需要想要改变内部表示时进行隔离好处是一旦需要更改,可以灵活的更改(内部重载或者更改实现),
坏处是增加了方法 在Android中有方法数限制
综合方案:对于JavaBean内部,使用成员变量的时候,可以在内部直接访问,外部访问必须进过get set方法,这样的话,因为是在内部访问的,所以需要更改的时候很容易找到,同时也减少了不必要方法数/调用的开销; -
不可变类如果进行多次变化,提供一个新的方法
String不可变,提供了一个配套的变化类StringBuilder,方便多次进行字符串拼接并且性能可靠;
-
不要为每一个get方法提供set方法,除非有很好的理由让类变成可变类,否则就是不可变的类,
- 不可变类有很多优点,节省内存,线程安全省资源,但是有一个缺点,在特定情况下存在可能的性能问题(如String一直被+连接时生成大量的String对象,解决办法是提供StringBuilder来构建更加多变的类)
-
如果类是可变的,也要尽量降低他的可变性,除非有非常强烈的理由把这个 方法/字段 变成非final的,否则每个方法/字段 都应该是final
-
复合优于继承:应该用复合和转发机制
- 复合转发机制:A类中包含B类,调用A类的方法中,转发调用B类方法,并且在中间插入某些操作
- 继承:A类继承B类,调用A类方法,转发调用super,并且在中间插入某些操作(Activity生命周期方法全都是如此)
- 包装类不适合与回调,因为回调对象提供的引用对象是其自身,并不是其包装类,导致包装类的方法失效....
- 只有当A真正的是B的子类的时候,才能使用继承,B确实是A,否则 应该是复合的关系
-
要么为继承设计,并提供详细的说明文档,要么就禁止继承
好的API应该描述一个给定的方法做了什么工作
-
接口优于抽象类
现有的类很容易被扩展,实现新的接口,而单继承特性让它很难继承抽象类
接口是提供扩展功能 的理想选择
接口允许我们构建非层次性结构,可以让两者毫无关联的在一起,如果用抽象类,随着需求的增大,可能会导致更加臃肿,导致组合爆炸
接口虽然不允许有实现,但是可以给每一个导出的接口写一个抽象的骨架实现,把接口和抽象类的优点结合起来(类似于上面的包装类),接口负责定义类型,骨架类负责实现()
例如:各种Abstract开头的类,比如AbstractList,AbstractMap实现了接口的一些通用方法,方便子类进行更好的编码:
如果一个接口有多个方法是子类都共有的,可以编写一个AbstractXXX骨架类,实现共有方法,子类便于更好的编码;抽象类的修改比接口的修改容易的多,抽象类可以任意增加具体的实现方法而不用修改子类,接口不行,接口一旦被公开,想再增加方法需要更改所有的实现类,成本极高
-
接口只应该用于定义类型
- 常量接口(接口中只包含一些具体的常量字段,不包含抽象方法),是错误的(还记得V影院的BaseActivity实现的接口吗 直接把常量都定义到一个接口里面去了)
- 静态工具类可以代替常量接口,并且静态导入让使用更加方便
-
类层次优于标签类
- 一种类负责实例化好几种不同的对象(形状类 实例化成圆形/正方形/三角形),导致内部代码臃肿,应该分成多个类分别实例化
- 用单个的类去区分功能,好过于用一个类去管理实例变化
-
用函数对象表示策略
实际上就是我们Android常用的匿名内部类,比如点击事件等等,
回调机制, 抽象方法 -
优先考虑静态成员类
- 四种嵌套类:静态成员类,非静态成员类,匿名类,局部类,后面三种都称之为内部类
- 非静态内部类存在一个this的外部类引用,
- 如果成员类不要求访问外部实例,则始终加上static修饰符
总结:
- 编码时刻遵循高内聚,低耦合,尽量减少外界对类的修改,并且对类的修改入口进行封装(比如set,get),便于后期扩展
- 复合(组合)优于继承,继承破坏了封装性和灵活性,并且使得类臃肿,如果非得用,可以用复合+转发机制代替继承;
- 接口优于抽象类,道理同上,如接口中有公共的实现方法,考虑编写Abstract骨架类,让子类更少的编写代码,复用逻辑;
- 类层次优于标签类(类中根据各种条件去进行各种操作的类),用类去分层而不是用if-else逻辑(简单工厂模式+类分层可以代替标签类)
- 回调,抽象方法
- 内部类尽量加上static,比如ViewHolder,