自学设计模式--1 单例模式

来源:互联网 发布:网店美工 编辑:程序博客网 时间:2024/06/05 09:31
写在前面
问:一个男人,从恋爱走向结婚,对于一个男人意味着什么?
答:牛进圈了,从此有了稳定的饲料来源,但想乱吃点别的什么就不太可能了……

1. 单例模式的定义
    官方定义:Ensure a class has only one instance,and provide a global point of access to it.确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

2.单例模式的特点
    优点:
  • 由于在内存中只有一个实例,减少了内存开支,减少了系统资源的开销。
  • 避免了对资源的多重占用;
  • 可以优化和共享资源的访问;
        
    缺点:
  • 单例模式没有接口,扩展困难;
  • 在并行的环境中,单例模式对测试不利;

3.单例模式的使用场景

在一个系统中,要求一个类有且仅有一个对象,如以下场景:
  •     系统要求生成唯一序列号环境;
  •     保存web页面上计数器的值,不必每次刷新都记录到数据库;
  •     创建对象的实例耗费的资源比较多;
    注意事项:
        ①解决线程不安全的问题:
            单例模式有饿汉式和懒汉式两种方式,推荐使用饿汉式,懒汉式存在风险。饿汉式代码见关键代码的Emperor类,下面给出懒汉式代码,说明见注释。

package com.pbi.pattern.singleton;/** * 此种单例模式存在风险(饿汉式) *  * @author 姓名 工号 * @version [版本号, 2013-5-13] * @see [相关类/方法] * @since [产品/模块版本] */public class EmperorI{    private static EmperorI emperor = null;        private EmperorI()    {        super();    }        /**     *      * <风险分析:     *      ①假设存在两个线程,线程A和线程B,     *      ②当线程A执行到 emperor = new Emperor时,正在申请内存分配,     *          此时线程B执行到 if(null == emperor),此时的返回结果不确定是true还是false     *          若是true,此时线程B 也创建了新的对象,导致业务逻辑的混乱>     * @return     * @see [类、类#方法、类#成员]     */    public static EmperorI getInstance()    {        if (null == emperor)        {            emperor = new EmperorI();        }        return emperor;    }        public static void say()    {        System.out.println("~~~ I am the Emperor XXX ~~~");    }    }

        ②考虑对象的复制情况
        单例模式类建议不要实现Cloneable接口,在Java中对象默认是不可以被复制的,实现了Cloneable接口,并重写了clone方法,则可以直接通过对象复制的方式创建一个新对象,对象复制是不用调用类的构造函数的,因此,即使是私有的构造函数,对象仍然可以被复制。

4.单例模式的使用案例
    4.1描述
        皇帝就是孤家寡人,皇帝类只能产生一个实例,所有对象对他的依赖都是相同的。   

    4.2类图

图1 单例模式类图
    4.3关键代码

Emperor类
/** * 此种单例模式存在风险(懒汉式) *  * @author 姓名 工号 * @version [版本号, 2013-5-13] * @see [相关类/方法] * @since [产品/模块版本] */public class EmperorII{    private static EmperorII emperor = new EmperorII();        private EmperorII()    {        super();    }        public synchronized static EmperorII getInstance()    {        return emperor;    }    }

Minister类
package com.pbi.pattern.singleton;/** * 大臣类 *  * @author 姓名 工号 * @version [版本号, 2013-5-13] * @see [相关类/方法] * @since [产品/模块版本] */public class Minister{        public static void main(String[] args)    {        EmperorI emperorI = EmperorI.getInstance();        emperorI.say();                EmperorI emperorII = EmperorI.getInstance();        emperorII.say();                EmperorI emperorIII = EmperorI.getInstance();        emperorIII.say();            }    }




参考资料:《设计模式之禅》--秦小波