创建型模式分为五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
- 单例模式:全局只存在一个对象,有懒汉模式,恶汉模式,DCL模式等。比如Application只有一个实例;
- 工厂模式:由一个工厂对象决定创建出哪一种产品类的实例。好处是将“类实例化的操作”和“使用对象的操作分开”,实现了解耦。比如Bitmap的创建;
- 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。由具体的工厂负责实现具体的产品实例。比如小米产品,可以由多个工厂实现,生成小米手机、小米笔记本、小米手表等;和工厂模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品,而工厂方法每个工厂只能创建一类;
- 原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型对象创建新的对象,是程序更高效。比如Java中clone()方法,浅拷贝和深拷贝;
- 建造者模式:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。优点是隐藏复杂的实现细节,易于解耦,方便扩展。比如AlertDialog、StringBuilder、Glide等;
一些问题
1.单例模式中DCL是线程安全的吗?为什么?怎么改进?
单例模式中DCL不一定线程安全,看如下代码:
public class Singleton {
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if (singleton == null){ // -----> ①
synchronized(Singleton.class){
if(singleton == null){
singleton = new Singleton();// ---> ②
}
}
}
return singleton;
}
}
singleton = new Singleton()
这个过程分为三部分:
memory=Singleton();//1:分配对象内存空间
singleton(memory);//2:初始化对象
singleton=memory;//3:设置singleton指向刚分配的内存地址,此时singleton!=null;
由于JVM为了优化指令,提高程序运行效率,可以对代码进行指令重排序。那么上述过程可能变成这样:
memory=Singleton();//1:分配对象内存空间
singleton=memory;//3:设置singleton指向刚分配的内存地址,此时singleton!=null;
singleton(memory);//2:初始化对象
这样有可能会造成问题,所以要添加volatile禁止指令重排序,代码如下:
public class Singleton {
//通过volatile关键字来确保安全
private volatile static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
网友评论