设计模式-单例模式(Singleton Pattern)

阅读 2
收藏
2019-09-04
原文链接:zdran.com

注意:阅读本文时,强烈建议先阅读下 OneMall 项目的概要设计

1. 需求

由于我们需要对接各大商城的 API,所以我们需要在 Supplier 模块实现各大商城的 API client,提供一个 client 供其他模块来调用。每个商城的 API client 只需要一个就可以了。这个 client 就可以使用单例模式

2. 实现

代码实现:

public class JdApiSingleton {
    private static final JdApiSingleton self = new JdApiSingleton();

    private JdApiSingleton() {
    }

    public static JdApiSingleton getJdApi() {
        return self;
    }

    /**
     * 获取商品信息
     *
     * @param url   地址
     * @param param 参数
     * @return 商品实体
     */
    public static GoodsDTO getGoodsInfo(String url, Map<String, Object> param) {
        String result = HttpClientUtil.get(url, param);
        return JSONObject.parseObject(result, GoodsDTO.class);
    }

    /**
     * 提交订单
     *
     * @param url   地址
     * @param param 参数
     * @return 订单信息
     */
    public static OrderDTO submitOrder(String url, Map<String, Object> param) {
        String result = HttpClientUtil.post(url, param);
        return JSONObject.parseObject(result, OrderDTO.class);
    }

单例模式比较简单,这里使用了”饿汉式”的设计,私有化构造方法,确保应用中只有一个实例,然后还有提供了其他各种 API,用于实现业务逻辑。

3. 类图

单例模式

单例模式的类图比较简单,只需要一个 Singleton 就可以实现单例模式。单例模式不仅仅只有一种实现方式,上面这种“饿汉式”式最简单的实现。有兴趣的可以说搜一下其他的实现方式,由于本文讨论的是设计模式,这里不再详细讨论别的实现方式。

4. 扩展

在内存中产生一个实例很简单,但是,在有些情况下我们可能需要固定数量的实例,用来提高应用的性能。比如在多线程的情况下,我们可能需要为每个线程分配一个实例。这个时候我们就可以在内存中生成固定数量的实例,数量与线程池的大小保持一致。

代码实现:

public class JdApiSingletonPool {
    //实例最大个数
    private static final int MAX_NUM = 4;
    private static final List<JdApiSingletonPool> pool = new ArrayList<>(MAX_NUM);

    private JdApiSingletonPool() {

    }

    //初始化单例池
    static {
        for (int i = 0; i < MAX_NUM; i++) {
            pool.add(new JdApiSingletonPool());
        }
    }

    /**
     * 获取实例
     *
     * @param index 下标
     * @return 如果下标越界返回 null
     */
    public static JdApiSingletonPool getJdApiSingleton(int index) {
        if (index < 0 || index >= MAX_NUM) {
            return null;
        }
        return pool.get(index);
    }

    // other api ...

我们通过初始化一个单例的集合来存储所有的单例。这样就能够保证内存中有固定数量的单例实例。

5. 总结

单例模式(Singleton Pattern): 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

这个定义有 3 个含义:

  1. 只能有一个实例(私有化构造方法)
  2. 自行实例化(自动初始化)
  3. 向整个系统提供这个实例(提供 get 方法获取自动初始化的实例)

单例模式的优点:

  1. 只有一个实例,节省了内存开销。减少了对象的创建和销毁的时间。
  2. 避免了对资源的多重占用。由于只有一个实例,在程序运行期间,只能有一个进程来操作这个实例。
  3. 全局访问。单例模式要求向整个系统提供这个实例,所以可以用来共享某些资源。

单例模式的缺点:

  1. 没有接口,不易扩展。如果需要新增一些 API 就需要对单例模式进行修改
  2. 单一职责原则冲突。一个单例实例一般不会只实现一种业务逻辑。

6. 使用实例

  1. Spring 容器中的 Java Bean 就是采用的单例模式。每个 Bean 都是单例的。
  2. Java 中的 JDBC 连接对象 也是采用的单例模式。每个 JDBC 连接 都是单例的。

转载请注明出处
本文链接:zdran.com/20190818.ht…

评论