本文首要内容
- 六大准则
- 单例形式
- 总结
算法和设计形式是程序员绕不过去的点,如何确保写的代码易扩展低耦合且bug少?本人接下来会总结常见的一些设计形式,希望能有所启发,在工作中能写出更牛逼的代码。
1、六大准则
在开发过程中需求留意6条准则,它们是指导性的准则,需求我们时刻上心,那么我们的代码将会十分优雅。
-
单一责任:就一个类而言,只要一个引起它改变的原因。简略来说,便是这个类功能单一,不要把过多的功能放到一个类中。其间最难的便是责任的划分。这通常是优化代码的第一步
-
开闭准则:对扩展敞开,对修正封闭。简略而言,要完成开闭准则,最好便是不要直接依靠完成类,而应该依靠抽象,这样才好扩展。它类似于战略形式,或许依靠倒置。开闭准则让程序更安稳、更灵活
-
里氏替换:一切引证基类的地方有必要能透明地引证子类,完成它比较简略,运用基类来声明目标即可。里氏替换能让扩展性更好
-
依靠倒置:它指一种特定的解耦形式,使得高层次模块不依靠于低层次模块的完成细节。在细节上,战略形式是最能体现这一准则的,一般来说它经过调用者指定完成,而本身只依靠于抽象。依靠倒置让项目拥有改变的能力
-
接口阻隔:类之间的依靠联系应该建立在最小接口上,意思便是说,不要对外露出不必要的接口
-
迪米特准则:一个目标应该对其他目标有最少的了解,它还有一个解说,只与直接的朋友通讯。
6大准则,其实都挺抽象的,只要结合实例,自己在心里揣摩,转化成自己的语言,才能有所收获,多想多看。
2、单例形式
单例形式,确保某一个类只要一个实例,并且自行实例化并向整个系统提供这个实例。许多时分,程序中某个类只需求一个单例在即可,特别是那些需求较多资源的类,如包含了线程池之类的。
其间:client指高层客户端,Singleton指单例类。
完成单例形式一般有如下关键点:
- 结构函数不对外敞开,一般为private
- 经过一个静态办法或许枚举回来单例目标
- 确定单例类的目标只要一个,尤其是在多线程环境下
- 确保单例类目标在反序列化时不会重新结构目标
完成单例一般有以下几种办法:
private static final Singleton mInstance = new Singleton();
private Singleton(){}
public static Singleton getSingleton(){
return mInstance;
}
这种形式被称为“饿汉式”,基本的条件它都具有了,比如私有结构办法,经过静态函数回来私有单例目标。但有同学可能会问了,这样写线程安全吗?
回忆虚拟机类加载机制一文,类加载阶段,会在初始化阶段履行 cinit 办法,将类中静态句子都履行一遍,所以上述代码中,mInstance
目标在类加载的初始化阶段就会被实例化了,当然就不会存在线程安全的问题了。
上述单例形式还有一个问题,在没开端用这个目标的时分,目标就已经被初始化了,假设这个目标一直不需求运用,那么这是否存在糟蹋内存的嫌疑?
private static Singleton2 mInstance;
private Singleton2(){};
public static synchronized Singleton2 getInstance(){
if (mInstance == null) {
mInstance = new Singleton2();
}
return mInstance;
}
这是另一种单例形式的完成,十分简略,相比于上一种写法,在不需求运用的时分它是null,节省了资源。但它也有一个缺陷,假如mInstance
目标已经不为null了,但调用 getInstance
办法时仍是需求同步,这很影响效率的。我们再来看下一种单例形式的写法:
private static volatile Singleton3 mInstance;
private Singleton3(){};
public static Singleton3 getInstance(){
if (mInstance == null) {
synchronized (Singleton3.class) {
if (mInstance == null) {
mInstance = new Singleton3();
}
}
}
return mInstance;
}
这种写法基本把一切问题都处理了,不会过早初始化目标,也不会每次都去同步。还有一种很优异的单例形式的写法:
private Singleton4(){};
public static Singleton4 getInstance(){
return SingleHolder.sInstance;
}
private static class SingleHolder{
private static final Singleton4 sInstance = new Singleton4();
}
一个类是否会被虚拟机所加载,首要看是否运用这个类。在上述的单例写法中,假如没有调用到getInstance
办法时,是不会运用到 SingleHolder
这个类的,也便是说,sInstance
目标一开端并不会被初始化,只要调用getInstance
时才会加载SingleHolder
类,sInstance
目标才会被初始化。这种办法既能确保单例目标唯一,也能确保线程安全,它也不会一开端就被初始化。
3、总结
记住六大形式,单一责任、开闭准则、里氏替换、依靠倒置、接口阻隔,迪米特准则。同时记住单例的关键要素,结构办法私有,静态单例,静态办法获取,同时留意线程安全。