本文介绍: 这篇教程不仅提供了单例模式的理论基础,还通过具体的Java代码示例展示了如何实现应用这种模式。简单理解,通俗易懂

引言

单例模式是一种常用的设计模式,用于确保在一个程序中一个类只有一个实例,并且提供一个全局访问点。这种模式在需要严格控制资源访问和分配的情况下非常有用。

单例模式简介

定义与用途

单例模式是一种创建设计模式,它确保一个类只有一个实例,并提供一个全局访问点。这个模式经常用于控制资源访问,如数据库连接文件系统

实现方式:

单例模式通常涉及以下几个关键步骤

  • 将构造函数设置为私有,防止外部通过new关键字创建实例。
  • 在类内部创建一个类的实例。
  • 提供一个公开的静态方法,供外部获取这个唯一的实例。

饿汉式

在类加载时就创建实例。这种方式是线程安全的,但可能会增加内存负担,因为实例不管是否需要都会被创建

懒汉式

在第一次需要实例时才创建。这种方式可以节省资源,但需要考虑多线程环境下的线程安全问题。

UML

在这里插入图片描述

使用场景

优势与劣势

单例模式在spring中的应用

单例模式在Spring框架中的应用是其核心功能之一,特别体现在Spring的Bean容器管理中。在Spring框架中,单例模式的应用主要集中在以下几个方面:

Bean的默认作用域:
在Spring中,默认情况下,所有在Spring配置文件定义的Bean都是以单例模式创建的。这意味着无论应用中有多少次对特定Bean的请求,Spring容器都会返回同一个Bean实例。
这种方式有助于节省资源,因为相同的Bean不会被多次创建。

BeanFactory和ApplicationContext:
Spring的BeanFactory和ApplicationContext提供了Bean的创建和管理机制。它们作为Bean的容器,负责实例化、配置和组装Bean。
这些容器自身也是以单例模式运行的,确保整个应用中有一个统一的Bean管理中心。

单例Bean的线程安全:
虽然单例Bean在Spring中只实例化一次,但Spring并不保证单例Bean是线程安全的。这意味着Bean的线程安全依赖于其自身的实现。
在设计单例Bean时,需要考虑其在多线程环境下的行为,确保状态管理正确性。

单例模式与依赖注入(DI):
Spring使用依赖注入(DI)机制来管理Bean之间的依赖关系。在单例模式下,依赖注入确保相同的Bean实例被注入到其他需要它的Bean中。
这种机制简化了对象之间的关系,并提高了代码的可测试性和可维护性。

配置与管理:
Spring的单例模式允许集中管理Bean的配置。由于每个Bean只有一个实例,因此其配置属性只需要设置一次,而无需在每次使用时重新配置。
这对于管理大型应用中的配置和属性尤其有用,可以提高效率和一致性。

饿汉式实现

public class A {

    private static A obj = new A(); // 类加载时即创建实例

    private A() {} // 私有构造函数

    public static A getA() {
        return obj;
    }

    public void doSomething() {
        // 方法实现
    }

}

懒汉式实现

public class A {
    private static A obj;

    private A() {} // 私有构造函数

    public static synchronized A getA() {
        if (obj == null) {
            obj = new A(); // 第一次调用时创建实例
        }
        return obj;
    }

    public void doSomething() {
        // 方法实现
    }
}

数据库连接示例

我们将通过创建一个JDBCSingleton类来展示单例设计模式的一个实际应用。这个类将被用于数据库操作,保证整个应用中只有一个数据库连接实例。
JDBCSingleton 类设计
JDBCSingleton类将包含:

JDBCSingleton

public class JDBCSingleton {

    // 静态成员仅持有JDBCSingleton类的一个实例
    private static JDBCSingleton jdbc;

    // 私有构造器防止其他类实例化
    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 = 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("姓名: " + rs.getString(2) + "t" + "密码: " + 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 = 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;
    }

}

JDBCSingletonDemo

public 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请输入你想在数据库中执行操作: ");
            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("按回车键继续...");
                    System.in.read();
                    break;
                }
                case 2: {
                    System.out.print("输入查看的用户名: ");
                    String username = br.readLine();

                    try {
                        jdbc.view(username);
                    } catch (SQLException e) {
                        System.out.println(e);
                    }
                    System.out.println("按回车键继续...");
                    System.in.read();
                    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("按回车键继续...");
                    System.in.read();
                    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("按回车键继续...");
                    System.in.read();
                    break;
                }
                default:
                    return;
            }
        } while (choice != 5);
    }
}

这个示例展示了如何在实际应用中使用单例模式来创建和管理数据库连接。通过这种方式,可以确保应用程序中的所有组件都使用相同的数据库连接实例,从而提高了效率和一致性。同时,这也减少了数据库连接的开销,因为连接实例只被创建一次并在整个应用中复用

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

原文地址:https://blog.csdn.net/qq_33129875/article/details/134648038

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_1639.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注