单例模式表示“定义一个类,该类只有一个实例,并提供一个全局访问点。”

换句话说,一个类必须确保只创建一个实例,并且该实例可以被所有其他类使用。

单例设计模式有两种形式

  • 早期实例化: 在加载时创建实例。
  • 懒惰实例化: 在需要时创建实例。

单例设计模式的优点

  • 节省内存,因为对象不会在每次请求时创建。单个实例被反复使用。

单例设计模式的使用场景

  • 单例模式主要用于多线程和数据库应用程序。它用于日志记录、缓存、线程池、配置设置等。

单例设计模式的 UML

3-1.jpg

如何创建单例设计模式?

要创建单例类,我们需要有类的静态成员、私有构造函数和静态工厂方法。

  • 静态成员: 由于静态特性,它只占用一次内存,它包含单例类的实例。
  • 私有构造函数: 它将防止从类外部实例化单例类。
  • 静态工厂方法: 这提供了单例对象的全局访问点,并返回实例给调用者。

了解单例模式的早期实例化

在这种情况下,我们在声明静态数据成员时创建类的实例,因此在类加载时创建类的实例。

让我们看看使用早期实例化的单例设计模式示例。

文件:A.java

class A { 
    private static A obj = new A(); // 早期实例将在加载时创建 
    private A() {} 

    public static A getA() { 
        return obj; 
    } 

    public void doSomething() { 
        // 编写你的代码 
    } 
}

了解单例模式的懒惰实例化

在这种情况下,我们在同步方法或同步块中创建类的实例,因此在需要时创建类的实例。

让我们看看使用懒惰实例化的单例设计模式的简单示例。

文件:A.java

class A { 
    private static A obj; 
    private A() {} 

    public static A getA() { 
        if (obj == null) { 
            synchronized (A.class) { 
                if (obj == null) { 
                    obj = new A(); // 实例将在请求时创建 
                } 
            }       
        } 
        return obj; 
    } 

    public void doSomething() { 
        // 编写你的代码 
    } 
}

类加载器在单例模式中的重要性

如果单例类被两个类加载器加载,将创建单例类的两个实例,每个类加载器一个实例。

序列化在单例模式中的重要性

如果单例类是可序列化的,你可以序列化单例实例。一旦序列化,你可以反序列化它,但它不会返回单例对象。

要解决这个问题,你需要覆盖 readResolve() 方法,它强制单例。它在对象反序列化后立即调用。它返回单例对象。

public class A implements Serializable { 
    // 你的单例代码 
    protected Object readResolve() { 
        return getA(); 
    } 
}

了解单例模式的实际示例

  • 我们将创建一个 JDBCSingleton 类。这个 JDBCSingleton 类包含私有的构造函数和自身的私有静态实例 jdbc。
  • JDBCSingleton 类提供了一个静态方法来获取其静态实例给外部世界。现在,JDBCSingletonDemo 类将使用 JDBCSingleton 类获取 JDBCSingleton 对象。

3-2.jpg

假设: 你已经在 MySQL 数据库中创建了一个名为 userdata 的表,该表有三个字段 uid, uname 和 upassword。数据库名称是 ashwinirajput,用户名是 root,密码是 ashwini。

文件:JDBCSingleton.java

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

class JDBCSingleton { 
    // 第一步 
    // 创建一个 JDBCSingleton 类 
    // 静态成员仅持有 JDBCSingleton 类的一个实例 
       
    private static JDBCSingleton jdbc; 
      
    // JDBCSingleton 防止从任何其他类实例化 
    private JDBCSingleton() { } 
    
    // 现在我们提供全局访问点 
    public static JDBCSingleton getInstance() {  
        if (jdbc == null) { 
            jdbc = new JDBCSingleton(); 
        } 
        return jdbc; 
    } 
      
    // 从插入、查看等方法中获取连接 
    private static Connection getConnection() throws ClassNotFoundException, SQLException { 
        
        Connection con = null; 
        Class.forName("com.mysql.jdbc.Driver"); 
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/ashwanirajput", "root", "ashwani"); 
        return con; 
        
    } 
      
    // 向数据库插入记录 
    public int insert(String name, String pass) throws SQLException { 
        Connection c = null; 
        
        PreparedStatement ps = null; 
        
        int recordCounter = 0; 
        
        try { 
            c = this.getConnection(); 
            ps = c.prepareStatement("insert into userdata(uname,upassword)values(?,?)"); 
            ps.setString(1, name); 
            ps.setString(2, pass); 
            recordCounter = ps.executeUpdate(); 
            
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            if (ps != null) { 
                ps.close(); 
            }
            if (c != null) { 
                c.close(); 
            }  
        } 
        return recordCounter; 
    } 

    // 从数据库查看数据    
    public void view(String name) throws SQLException { 
        Connection con = null; 
        PreparedStatement ps = null; 
        ResultSet rs = null; 
         
        try { 
            con = this.getConnection(); 
            ps = con.prepareStatement("select * from userdata where uname=?"); 
            ps.setString(1, name); 
            rs = ps.executeQuery(); 
            while (rs.next()) { 
                System.out.println("Name= " + rs.getString(2) + "\t" + "Password= " + rs.getString(3));   
            } 
        
        } catch (Exception e) { 
            System.out.println(e);
        } finally { 
            if (rs != null) { 
                rs.close(); 
            }
            if (ps != null) { 
                ps.close(); 
            }
            if (con != null) { 
                con.close(); 
            }  
        } 
    } 
    
    // 更新给定用户名的密码 
    public int update(String name, String password) throws SQLException { 
        Connection c = null; 
        PreparedStatement ps = null; 
        
        int recordCounter = 0; 
        try { 
            c = this.getConnection(); 
            ps = c.prepareStatement(" update userdata set upassword=? where uname='" + name + "' "); 
            ps.setString(1, password); 
            recordCounter = ps.executeUpdate(); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            if (ps != null) { 
                ps.close(); 
            }
            if (c != null) { 
                c.close(); 
            }  
        } 
        return recordCounter; 
    } 
      
    // 从数据库中删除数据  
    public int delete(int userid) throws SQLException { 
        Connection c = null; 
        PreparedStatement ps = null; 
        int recordCounter = 0; 
        try { 
            c = this.getConnection(); 
            ps = c.prepareStatement(" delete from userdata where uid='" + userid + "' "); 
            recordCounter = ps.executeUpdate(); 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } finally { 
            if (ps != null) { 
                ps.close(); 
            }
            if (c != null) { 
                c.close(); 
            }  
        } 
        return recordCounter; 
    } 
} // JDBCSingleton 类结束

文件:JDBCSingletonDemo.java

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

class JDBCSingletonDemo { 
    static int count = 1; 
    static int choice; 
    public static void main(String[] args) throws IOException { 
        
        JDBCSingleton jdbc = JDBCSingleton.getInstance(); 
        
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
        do {  
            System.out.println("数据库操作"); 
            System.out.println(" --------------------- "); 
            System.out.println(" 1. 插入 "); 
            System.out.println(" 2. 查看 "); 
            System.out.println(" 3. 删除 "); 
            System.out.println(" 4. 更新 "); 
            System.out.println(" 5. 退出 "); 
             
            System.out.print("\n"); 
            System.out.print("请输入你想在数据库中执行的操作: "); 
             
            choice = Integer.parseInt(br.readLine()); 
            switch (choice) { 
                case 1: { 
                    System.out.print("输入要插入数据库的用户名: "); 
                    String username = br.readLine(); 
                    System.out.print("输入要插入数据库的密码: "); 
                    String password = br.readLine(); 
                     
                    try { 
                        int i = jdbc.insert(username, password); 
                        if (i > 0) { 
                            System.out.println((count++) + " 数据插入成功"); 
                        } else { 
                            System.out.println("数据未插入");   
                        } 
                         
                    } catch (Exception e) { 
                        System.out.println(e); 
                    } 
                     
                    System.out.println("按 Enter 键继续..."); 
                    System.in.read(); 
                     
                } // case 1 结束
                break; 
                case 2: { 
                    System.out.print("输入用户名: "); 
                    String username = br.readLine(); 
                 
                    try { 
                        jdbc.view(username); 
                    } catch (Exception e) { 
                        System.out.println(e); 
                    } 
                    System.out.println("按 Enter 键继续..."); 
                    System.in.read(); 
                     
                } // case 2 结束
                break; 
                case 3: { 
                    System.out.print("输入要删除的用户ID: "); 
                    int userid = Integer.parseInt(br.readLine()); 
                 
                    try { 
                        int i = jdbc.delete(userid); 
                        if (i > 0) { 
                            System.out.println((count++) + " 数据删除成功"); 
                        } else { 
                            System.out.println("数据未删除");   
                        } 
                         
                    } catch (Exception e) { 
                        System.out.println(e); 
                    } 
                    System.out.println("按 Enter 键继续..."); 
                    System.in.read(); 
                     
                } // case 3 结束
                break; 
                case 4: { 
                    System.out.print("输入要更新的用户名: "); 
                    String username = br.readLine(); 
                    System.out.print("输入新密码: "); 
                    String password = br.readLine(); 
                     
                    try { 
                        int i = jdbc.update(username, password); 
                        if (i > 0) { 
                            System.out.println((count++) + " 数据更新成功"); 
                        } 
                         
                    } catch (Exception e) { 
                        System.out.println(e); 
                    } 
                    System.out.println("按 Enter 键继续..."); 
                    System.in.read(); 
                     
                } // case 4 结束
                break; 
                 
                default: 
                    return; 
            } 
             
        } while (choice != 5);  
    } 
}

输出

3-3.jpg
3-4.jpg
3-5.jpg

标签: Design Patterns, Design Patterns教程, 设计模式, 软件设计, 结构型模式, 行为型模式, 单例模式, 工厂模式, 观察者模式, 中介者模式, 访问者模式