抽象单例:一种通用的单例

背景

单例的一般写法,大家基本都会,这里特指具有以下特征的单例:
1.单例
2.需要延迟加载
3.线程安全
看一下这个类的写法(JAVA):

public class A {
    private static final AtomicReference<A> ref = new AtomicReference<>();

    private A() {
    }

    public static A get() {
        A ret = ref.get();
        if (ret == null) {
            synchronized (ref) {
                if (ref.get() == null) {
                    ret = new A();
                } else {
                    ret = ref.get();
                }
            }
        }
        return ret;
    }
}

问题:

这样写是没问题。我们大部分时候也都这么写。
如果我们有好几个类都要写单例怎么办,A,B,C….?挨个搞一遍?万一以上代码出了问题,需要修复,再挨个修复一遍?显然不能这么搞。

解决方法

我观察了一下这些类的规律,整个类的代码基本相同,只有对象创建部分不同。根据OO的基本特性,我们可以把这部分不一样的代码,放到子类里去,延迟实现。

我们可以这样一个辅助类,我称它为“抽象单例”:

/**
 * 线程安全的抽象单例
 * 
 * @author zhmt
 * @createdate 2016年3月4日 下午4:39:50
 * @param <T>
 */
public abstract class AbstractSingleton<T> {
    private final AtomicReference<T> ref = new AtomicReference<T>();

    public T get() {
        T ret = ref.get();
        if (ret == null) {
            synchronized (this) {
                if (ref.get() == null) {
                    ret = newObj();
                    ref.set(ret);
                } else {
                    ret = ref.get();
                }
            }
        }
        return ret;
    }

    protected abstract T newObj();
}

通过这个类,我们就把对象创建的操作延后了。

现在,再看我们怎么实现A的单例:

public class A {
    public static final AbstractSingleton<A> objHolder = new AbstractSingleton<A>() {
        protected A newObj() {
            return new A();
        }
    };

    private A() {
        A.objHolder.get();
    }
}

这里只需要写几行简单的代码,而不是复杂易错的初始化过程,这样,以后所有类似的单例都得到了简化。
获取A的单例:
A.objHolder.get();

这样,以后再需要单例的时候,我只需要声明一个AbstractSingletion对象,并实现newObj方法即可。

如果你有更好的办法,欢迎讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值