目前,在看一本设计模式之禅的一本书(电子版),感觉写的还不错,语音也挺幽默的,例子也有代表性,
所以,就想在看后有个更深印象,也顺便记录下学习之旅,是用的语音也是Java.
第一个,当然是单例模式:
所谓单例,当然就是只有一个实例.不允许该类创建出多个实例对象.
我们都知道,一般我们创建一个对象,直接使用new关键字,然后调用对应参数的构造方法创建实例对象.
例如:
//例如我们有各类为Singleton public class Singleton { } //所以一般情况我们创建实例对象的方式为: Singleton single = new Singleton();
所以,
1,当我们把一个类的构造方法私有化,外部就不能创建该对象(至少不能使用new关键字).
2,不过,既然创建出了个类,我们就是为了用他的,所以,要在内部创建好实例,并给出一个静态方法来获取该类的实例(毕竟我们这个类的构造方法私有化了).
3,同时,在该类中创建的实例,一定是不可修改的,不然就不是单例了,故应该将该类创建的实例,定义为 static final的,使该实例不能修改,确保一旦创建出,就是唯一的.
代码如下:
public class Singleton { private Singleton(){ } private static final Singleton single = new Singleton(); public static Singleton getInstance(){ return single; } }
基本上只要符合这种要求,单例模式就出炉了.
一般,单例模式有两种实现方式.上面那种为 饿汉式(在类加载的时候就将该实例对象创建好,等待别人获取).
另一种为懒汉式(在别人第一次访问的时候再将对象实例创建).
public class Singleton { private Singleton(){ }
private static Singleton single = null; public static Singleton getInstance(){ if(single!=null){ single = new Singleton(); } return single; } }
这两种实现方式最重要的区别在于该单例类何时实例化.
饿汉式为在类加载的时候就创建好实例.
而懒汉式则在其他类第一次访问的时候再进行创建.
不过,懒汉式,由于在创建实例的时候,并不是,立即创建,而是需要判断是否已经存在实例了,
所以,在此处很有可能存在线程安全问题.
public class Singleton { private static Singleton single= null; private Singleton() { } public static Singleton getInstance() { if(single== null) { synchronzied(Singleton.class) { if(single== null) { single= new Singleton(); } } } return instance; } }
所以,但看这两种实现方式,明显懒汉式每次在别人访问拿实例的时候,都需要进行同步,
这样,无疑会使得相对消耗cpu资源多一些,毕竟每次只有访问完成后才将锁释放掉.
所以,一般使用单例模式,比较推荐使用饿汉式,1,代码简洁.2,消耗小.
不过单例模式,由于只能存在一个对象,所以,很容易出现并发问题.
所以,系统中,有时会考虑有上限的多例模式.
import java.util.ArrayList; import java.util.Random; public class MultiInstance { private MultiInstance(){ } private static int maxNumOfInstance = 4; //创建一个集合来装载这些实例 private static ArrayList<MultiInstance> instances = new ArrayList<MultiInstance>(); //利用静态代码块加载所需要的实例 static { for(int i=0; i<maxNumOfInstance; i++){ instances.add(new MultiInstance()); } } //随即获取一个实例对象 public static MultiInstance getInstance(){ int number = new Random().nextInt(maxNumOfInstance); return instances.get(number); } }
单例模式在23中设计模式中算是比较简单的一种,应用也是比较广泛的,比如在spring中,每一个Bean都是默认为单例的.
不过在使用单例模式的时候,需要注意,若我们这个单例对象长时间不使用,JVM可能会认为该实例为一个垃圾,在cpu空闲的时候将其回收,
我们下次再次调用产生的对象,就会是一个新的实例.所以,若该实例,是有记录信息,或者状态的时候,一定要谨慎使用单例模式.