设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结使用
设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样
看过好多关于设计模式的文章,这篇还是不错的,讲的很详细。
从定义上就能看出设计模式的重要性和实用性。在代码中使用合适的设计模式可以在提升代码结构合理性,降低耦合度。常用的设计模式有23种,这里只列举出目前用到过的,其他的以后再补充。
1.单例模式
单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例。
- 从单例模式的定义也能看出他的大概使用场景,它可以用来控制实例的数量。
注意,因为这个模式本身并不难,而且用起来会省去大量的创建实例代码,所以项目中会经常用到。
但是一定要注意使用场景,不然会出现很多意想不到的问题。- 写网络请求框架的时候注意,并发请求的时候,使用单例会造成结果异常。
- 创建Fragment 的时候使用单例,会造成内存泄露。
单例模式的写法
1.普通写法
-私有化构造方法,保证只有在类内部才能创建实例
-定义一个私有的实例变量
-向外提供一个创建实例的方法
public class BaseSingleton {
private static BaseSingleton mInstance;
//私有化构造方法,不让在外部直接创建对象
private BaseSingleton(){
}
//提供一个公有的方法提供对象实例
public static BaseSingleton getInstance() {
if (mInstance==null) {
mInstance=new BaseSingleton();
}
return mInstance;
}
}
上述代码直接用BaseSingleton.getInstance()即可创建实例,但是在多线程的情况下是不安全的。可能会创建多个实例,违背了该模式的初衷。因此需要改进.
改进1:
在getInstance()方法上直接加锁,可以解决线程安全问题
/**为解决线程安全问题,直接在方法上加synchronized
* 1.每次调用getInstance都要对对象上锁,造成性能打折
* 2.我们只需在第一次调用的时候加锁即可
* @return
*/
public synchronized BaseSingleton getInstance2() {
if (mInstance==null) {
mInstance=new BaseSingleton();
}
return mInstance;
}
这种解决办法造成的问题也在注释上说明了,因为每次调用getInstance()方法,不管是不是已经创建过对象,都会加锁(理论上我们只需要在第一次创建对象的时候加锁即可),所以会降低性能,并不是一个合理的方案。
继续改进,既然不能直接在创建方法上添加synchronized,那么我们就在第一次创建对象的时候加锁。
/**新问题
* 1.java指令中创建对象和赋值操作是分开进行的,也就是说mInstance=new BaseSingleton();语句是分两步执行的
* 但是jvm并不能保证这两个操作的执行顺序,也就是说JVm有可能先给实例分配空间,然后直接赋值给mInstance,然后再去初始化Singleton实例,
* 这样就可能出错
*
* 我们以A、B两个线程为例:
a>A、B线程同时进入了第一个if判断
b>A首先进入synchronized块,由于instance为null,所以它执行instance = new Singleton();
c>由于JVM内部的优化机制,JVM先画出了一些分配给Singleton实例的空白内存,并赋值给instance成员(注意此时JVM没有开始初始化这个实例),然后A离开了synchronized块。
d>B进入synchronized块,由于instance此时不是null,因此它马上离开了synchronized块并将结果返回给调用该方法的程序。