java-設計模式-單例模式

單例模式

一种创建型设计模式 让你能够保证一个类只有一个实例 并提供一个访问该实例的全局节点

一个类只有一个实例,且该类能自行创建这个实例的一种模式。

簡單的對比就是:

例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,
或出现各个窗口显示内容的不一致等错误。

特點

单例类只有一个实例对象;
该单例对象必须由单例类自行创建;
单例类对外提供一个访问该单例的全局访问点。

應用場景

需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC。
某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。
某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
频繁访问数据库或文件的对象。
对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,如果有多个实例,则系统会完全乱套。
当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。
如 Web 中的配置对象、数据库的连接池等

 

實現步驟:

在类中添加一个私有静态成员变量用于保存单例实例。

声明一个公有静态构建方法用于获取单例实例。

在静态方法中实现"延迟初始化"。 该方法会在首次被调用时创建一个新对象, 并将其存储在静态成员变量中。 
此后该方法每次被调用时都返回该实例。 将类的构造函数设为私有。 类的静态方法仍能调用构造函数, 但是其他对象不能调用。 检查客户端代码, 将对单例的构造函数的调用替换为对其静态构建方法的调用。

 

懶漢式的單例模式

/**
 * 懶漢式單例設計模式
 *
 * 特點;'类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例
 *
 */
public class LaziSingleton {
    //volatile,若变量发生变化,这同步到所有的线程中。
    private static volatile LaziSingleton instance =null;
    //私有有構造函數
    private LaziSingleton(){}

    public static synchronized LaziSingleton getInstance(){
        if (instance == null){//如果對象還沒有被創建,那就新建一個實列
            instance =  new LaziSingleton();
        }
        return instance;
    }
    /**
     * 编写的是多线程程序,则不要删除上例代码中的关键字 volatile 
     * 和 synchronized,否则将存在线程非安全的问题。
     */
}

 

餓漢式的單例模式

/**
 * 餓漢式單例
 *
 * 特點:类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了
 */
public class HungrySingleton {
    //加載的時候就創建實列
    private static final  HungrySingleton instance = new HungrySingleton();

    private HungrySingleton(){}

    private static HungrySingleton getInstance(){
        return instance;
    }
    /**
     * 在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,
     * 所以是线程安全的,可以直接用于多线程而不会出现问题。
     */
}

 

簡單實踐驗證

 

建立一個單例模型的類:

/**
 * 单例模式
 */
public class President {

    //volatile,若变量发生变化,这同步到所有的线程中。
    private static volatile President instance = null;


    /**
     *  私有化构造函数,避免使用new创建的实例
     */
    private President(){
        System.out.println("new a President");
    }

    /**
     * synchronized关键字作用:保证方法或者代码在运行时,得到锁。
     *  统一时刻只有一个方法执行。保证共享变量内存可见性
     *  可见性
     * @return
     */
    //运行该方法的时候只有一个线程能够得到锁。避免出现创建两个实例的情况
    public static synchronized President getInstance() {
        if (instance == null){
            instance = new President();
        }else {
            System.out.println("exist a President");
        }
        return instance;
    }

    //
    public void something(){
        System.out.println("president--end");
    }
}

測試代碼:

public class SingletonTest {
    public static void main(String[] args) {
        President president1 = President.getInstance();
        President president2 = President.getInstance();
        president1.something();
        president2.something();

        /**
         * 判断是否为同一实例
         */
        if (president1 == president2){
            System.out.println("president1 == president2");
        }else {
            System.out.println("president1 != president2");
        }
    }
    /**
     new a President
     exist a President
     president--end
     president--end
     president1 == president2
     */
}

 

posted @ 2020-09-13 15:41  小丑quan  阅读(185)  评论(0)    收藏  举报