設計模式筆記(八)——單例模式

1. 是什麼——定義

一個類只有一個對象實例。java

2. 爲何——特色

保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。多線程

3. 何時用——適用性

l  一個全局使用的類頻繁地建立與銷燬,而須要考慮節省系統資源的時候。併發

l  須要考慮資源共享的時候。高併發

4. 怎麼用——實際應用

需求:spa

GUI下點擊按鈕只能出現一個對話框線程

初始設計:

public class MainFrame extends JFrame {
    private JPanel contentPane;
    
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    MainFrame frame = new MainFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    public MainFrame() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 625, 364);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(null);
        setContentPane(contentPane);
        
        //關鍵代碼
        JButton button = new JButton("點擊我!");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new Dialog().setVisible(true);
            }
        });
        button.setBounds(225, 109, 159, 56);
        contentPane.add(button);
    }
}

使用單例模式:

public class Dialog extends JFrame {
    //關鍵代碼
    private static Dialog instance = new Dialog();
    public static Dialog getInstance() {
        return instance;
    }
    
    private JPanel contentPane;
    
    //構造方法私有化
    private Dialog() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(null);
        setContentPane(contentPane);
        
        JLabel label = new JLabel("對話框。。。");
        label.setFont(new Font("宋體", Font.PLAIN, 18));
        label.setBounds(157, 117, 165, 28);
        contentPane.add(label);
    }
}
JButton button = new JButton("點擊我!");
button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Dialog.getInstance().setVisible(true);
    }
});

 

5. 多線程下的單例模式

多線程下的高併發,會出現兩個線程同時搶到構造方法的資源,形成非單例現象。設計

須要解決,常見的解決方案有兩種:code

5.1  懶漢單例模式

特色:只有第一次須要加載的時候才調用惟一的一次構造方法。orm

private static Dialog instance;
public static Dialog getInstance() {
    if (instance == null) {
        synchronized (instance) {
            if (instance == null) {
                instance = new Dialog();
            }
        }
    }
    return instance;
}

//其中,第一層if是爲了提升程序執行效率
//(若是沒有這層判斷,若是instance原本就不爲null,但還要進入synchronized代碼塊,會使程序執行效率大大下降!)

5.2  餓漢單例模式

特色:該類加載到內存時就調用惟一的一次構造方法。對象

private static Object instance = new Object();
相關文章
相關標籤/搜索