您的位置:首页 > 编程语言 > Java开发

Java设计模式之单例设计模式

2016-07-25 11:45 316 查看
第一篇写设计模式的博客,解释下何为设计模式.

很多人觉得设计模式很高大上,从而产生一种误区:在学习java web 或者android的时候都会想,现在还不是学设计模式的时候,等真正开发上一两年的时候学起来或许更有帮助些。然而并非不是那样的,所以这是个误区。

那么何为设计模式?

设计模式就是一些大牛骨灰级Java玩家,在玩Java的时候,玩多了发现项目里有些java可以抽象化,确切的说可以普遍化,那么会将一些共同的代码抽取出来作为一定的设计方式,并给它一个具体的名称,这是一种抽象出来的成果。另外一种,就是这些玩家玩的多了,就更会玩了。那么就想可不可以创造出一些固定的代码,以后在一些特定的情况下直接套用而且比原来的惯用搬砖方式更加适合甚至达到王祖蓝呢?这是一种主观创造的成果。这些成前人的精髓,是Java开发者的幸福,更是一种传承。

进入正题之前,安利下之前的博文:http://blog.csdn.net/u014665060/article/details/51241526这篇是有关android recyclerview的集大思成的成果,可拿来就用,还可以随便修改符合自己的需求。欢迎star或者fork(万分感射)

好了,单例设计模式来了。很多开发者都懂,都会用,那么为什么还要讲呢?最近小编去研究了下,发现温故而知新说的没错。那么作为开篇这里也重复下吧。实现单例设计模式的目标,是要保正在程序运行期间,在创建对象的时候保持唯一,在重复创建不会创建出新的对象(分配新的内存空间)。好,这种使用场景往往出现在一些大内存开销的对象身上。例如IO,数据库,application等等。

实现单例设计的方式:

1.饿汉式

老外叫它饿汉式是在类初始化的时候就已经创建好了对象,就等这准备使用了。就等于已经老婆娶到了,红本子也领到了, 下一步就等着生猴子了。这就叫饿汉式,怎么,你想歪了?

具体我们来看下代码如何实现:

/**
* Created by Marshon.Chen on 2016/7/25.
* DESC:单例设计模式:饿汉式
*/
public class Pattern {
private Pattern (){} //1.构造函数私有化
private static Pattern p=new Pattern(); //2.创静态的单例
public static Pattern getInstance(){  //3.对外暴露共有的访问方法
return p; }}
2.懒汉式

这种模式步骤基本也是三步,只不过区别在于2.,3 。懒汉式并不是在类加载的时候就创建了单例对象,而是在外面访问共有的方法时候才创建。就比如,老婆还没有娶,
4000
本子还没领,硬是要到大喜日子的时候才领,完了吧立马造人。反过来说,就是等于造人的时候才去领证,现在流行的也是这种模式。诶,你们好污啊~~~

具体我们来看下代码如何实现:

/**
* Created by Marshon.Chen on 2016/7/25.
* DESC:单例设计模式:懒汉式
*/
public class Pattern {
private Pattern (){} //1.构造函数私有化
private static Pattern p; //2.声明静态对象
public static synchronized Pattern getInstance(){  //3.对外暴露共有的访问方法,并创建对象
return p==null?new Pattern():p; }}
3.DCL方式(Double Check Lock)

双判null,这中情况是目前最通用的实现单例方式,这种方式解决了两个问题:1.第一层判空避免了不必要的同步。2.第二层判空是为了创建单例。这是解决了Java处理器允许乱序执行的有效做法。在第一次加载时候才创建对象,利用率高,但同时第一次加载稍微反应慢。但那都不是事,功大于过。

/**
* Created by Marshon.Chen on 2016/7/25.
* DESC:单例设计模式:懒汉式-DCL
*/
public class Pattern {
private Pattern (){} //1.构造函数私有化
private static Pattern p; //2.声明静态对象
public static  Pattern getInstance(){  //3.对外暴露共有的访问方法,并创建对象
if (p==null){
synchronized (Pattern.class){
if (p==null){
p=new Pattern();
}
}
}
return p;
}
}

4.静态内部类实现

DCL方式有点颇多,安全性高,并解决了大部分情况下的并发问题,与此同时,也带了在很小几率上的失效的问题。那么在高并发的情况下,应该如何完善单例设计模式呢?

我喝口水润下口先,各位爷先看下代码:

/**
* Created by Marshon.Chen on 2016/7/25.
* DESC:单例设计模式:懒汉式-DCL
*/
public class Pattern {
private Pattern (){} //1.构造函数私有化
private static Pattern p; //2.声明静态对象
public static  Pattern getInstance(){  //3.对外暴露共有的访问方法,并创建对象
if (p==null){
synchronized (Pattern.class){
if (p==null){
p=PatternHolder.instance;
}
}
}
return p;
}

private  static class PatternHolder{
private static Pattern instance=new Pattern();
}
}

这种方式主要解决线程安全问题:在第一次加载Pattern时并不会初始化instance,只有调用getInstance时才会导致instance被初始化。因此,第一次调用getInstance的时候才会导致PatternHolder的时候被加载,并创建静态对象,这种方式即能保证线程的安全,同时也能保证对象唯一性。这也是Java web服务端推荐使用的实现方式。

4.容器实现单例模式

下面介绍一个非常有趣本人也非常喜欢的一种方式。这种方式在类加载的时候将对象统一用一个map容器来进行管理。在使用key作为标志来查找对象示实例。这洋就能够实现多个单例对象的管理,非常方便。降低了用户的使用成本,提高代码观赏性,同时也减低了耦合度。

/**
* Created by Administrator on 2016/5/26.
*/
public class LogicService {

private static final String TAG = "LogicService";

private static HashMap<String,Object> singleInstanceMap = new HashMap<String, Object>();
private LogicService()
{
}
@Deprecated  //获取单例实例,如果为null就创建实例,并添加到管理
public static <T extends Object> T getSingletonManagerForClass(Class<T> cls)
{
T mgr = null;
String className = cls.getSimpleName();
if(singleInstanceMap.containsKey(className))
{
mgr = (T) singleInstanceMap.get(className);
}
if(mgr==null)
{
try
{
mgr =  (T) cls.newInstance();
}
catch (IllegalAccessException e)
{
Log.e(TAG, e.getMessage());
}
catch (InstantiationException e)
{
Log.e(TAG, e.getMessage());
}
if (mgr != null)
{
singleInstanceMap.put(cls.getSimpleName(), mgr);
Log.d(TAG, String.format("findByLogicManagerClass result: %s", mgr.getClass().getName()));
}
else
{
Log.e(TAG, String.format("fail to find logic manager %s", cls.getSimpleName()));
}
}
return mgr;
}

今天先介绍到这里吧。。。。 我上面那个demo求Fork,我还会对动画方面进行继续拓展更新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: