本文首要内容

  • 六大准则
  • 单例形式
  • 总结

算法和设计形式是程序员绕不过去的点,如何确保写的代码易扩展低耦合且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、总结

记住六大形式,单一责任、开闭准则、里氏替换、依靠倒置、接口阻隔,迪米特准则。同时记住单例的关键要素,结构办法私有,静态单例,静态办法获取,同时留意线程安全。