一、面向对象六大原则
单一职责原则(SRP):一个类应该只负责一个部分,这个责任的划分并不明确,我的理解就是说不要把应该拆分的功能放在一个类里,从而松耦合,提高扩展性。具体理解还是要结合书上的托片加载器的例子。
开闭原则(OCP):系统对扩展开放,对修改封闭。要在尽量不修改原有代码的基础上对功能进行扩展,也就要求代码有很高的可扩展性。其实这几个原则都是设计模式的共同目标,很多地方都能得到体现。
里氏替换原则(LSP):凡是父类可以出现的位置,子类对象也应该可以出现并让用户感受不到区别。也就是说,子类要将父类要求的功能全部实现,相关部分依赖的是父类对象。
依赖倒置(DIP):高层不应该依赖低层模块,两者都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。简单的说,就是类之间不依赖具体的实现类,而是依赖抽象类和接口。面向接口编程,大大提高可扩展性。
接口隔离原则(ISP):客户端不应该依赖它不需要的接口,也就是把接口进行拆分,接口数量和继承复杂度增加,进一步松耦合。
迪米特法则(LOD):一个类应该只和他直接的朋友进行通信,也就是减少类之间的依赖,对于一个功能的实现,只依赖一个代理类(例如让中介找房子),让这个类来依赖其他类进行处理。
二、单例模式
如果一个类在整个系统中只需要提供一个对象,那么就应该使用单例模式,对于一些初始化过程复杂的类,这样做可以大大减少开销。
实现:首先要用private封住自身无参的构造器,也就是不暴露直接创建实例的方法。
1.维护一个私有的静态的自身类实例并直接实例化,暴露返回该实例的接口:
private static final Teacher t=new Teacher();
public Teacher getInstance(){
return t;
}
2.第一种方案的缺点是一开始就对对象进行了初始化,而不是在需要时才进行初始化创建,所以优化就是在需要时创建:
private static final Teacher t;
public Teacher getInstance(){
synchronized(Teacher.class){
if(t==null){
t=new Teacher();
}
}
return t;
}
synchronized关键字是为了保证创建过程的同步性,因为多线程情况下实例化可能多次执行。3.第二种还是有缺点,原文没有说清楚,应该比较复杂。建议使用下面的静态内部类形式:
private static class TeacherHolder{
private static final Teacher t=new Teacher();
}
public Teacher getInstance(){
return TeacherHolder.t;
}
这样的话只会在使用时创建,而且线程安全。
4.使用枚举单例:
public enum Teacher{
INSATNCE;
}
5.使用容器:
简单的说就是把这些单例模式的单例对象都存在一个管理类的静态Map中。
安卓中获取系统服务就是这种思路,刚开始的时候所有系统服务都会被注册到一个Map中,我们调用的getSystemService就是用key取出这个单例服务对象。
三、Builder模式
在安卓中最常见的Builder就是弹出框的创建了吧,使用Builder可以用链式语法构建一个实例,在其中定制对象的各个属性。
这个模式意义在于将创建过程分离出来,用户可以自由扩展定制对象的各个部分,类无需也不应该暴露出set接口,一次初始化后不允许更改,保证了对象无法随意修改。
实现思路也很简单,在Builder的设置字部件的方法返回自身,在create中创建一个目标实例并根据设置的参数进行定制即可。
对用户隐藏创建细节,设计更加合理了。
四、原型模式
原型模式的实现就是克隆(调用对象的clone方法),直接将原型对象的二进制数据复制到新实例中。这适用于需要产生一个初始化过程开销比较大的对象,或者说有一个对象不期望被修改,而有的地方需要使用这个对象,这时候也可以克隆一个出来。
实现比较简单,就是重写clone方法,在此之前要让类实现Cloneable接口,否则调用clone会出错。
在clone中创建一个实例并将自身参数配置给他,需要注意的是如果将自身的对象属性直接赋值给新对象,实际上是将两个引用指向一个地址(引用类型和基本类型的区别)(浅拷贝),想要产生新的对象属性就要调用原对象属性的clone方法。
安卓中Intent重写了clone,返回了用自身作为参数创建的实例,对应的构造器接收一个Intent作为参数,内容就是copy各个属性到自身。
需要注意的是原型模式并不调用构造器!!!