java设计模式学习之【对象池模式】

news2024/12/27 4:39:22

文章目录

  • 引言
  • 对象池模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 对象池模式在Spring中的应用
  • JDBC对象池示例
  • 代码地址
  • 小结

引言

对象池模式在资源管理和性能优化方面发挥着重要作用。这种模式通过重复使用已经初始化的对象,而不是频繁创建和销毁,减少了系统的开销。这对于处理如数据库连接、线程和图形对象等资源密集型和性能敏感的系统尤为重要。该模式是属于23种设计模式之外的补充模式。

对象池模式简介

定义与用途

对象池模式是一种创建型设计模式,用于管理和重用对象集合。当一个客户端请求一个新对象时,该模式先检查是否有现有的对象可用,而不是创建一个新对象。如果有可用的对象,它将被重用,否则,创建一个新对象并添加到池中。

实现方式

对象池模式通常涉及以下几个关键组件:

  • 对象池类:负责创建和管理对象池。
  • 池化对象:池中管理的对象。
  • 客户端:请求从池中获取对象的用户。
  • 接口/抽象类:定义对象的创建、重用和释放的规范。

工厂方法模式可以用来封装对象的创建逻辑。然而,它在创建之后不管理这些对象,而对象池模式则跟踪它创建的对象。
对象池通常实现为单例。

使用场景

  • 资源重用:当系统中对象的创建和销毁开销显著时。
  • 性能要求:在性能敏感的应用中,减少创建和销毁对象的次数。
  • 资源限制:在资源受限的情况下,如数据库连接或线程池。

优势与劣势

  • 优势
    提高性能:通过重用现有对象减少创建和销毁对象的开销。
    资源管理:有效管理稀缺资源,如数据库连接。
  • 劣势
    管理复杂性:维护对象池增加了系统的复杂性。
    潜在的资源浪费:如果池中对象很少被重用,可能会导致资源浪费。

对象池模式在Spring中的应用

在Spring框架中,并没有直接实现对象池模式,但它提供了相关的支持,使得我们可以方便地实现该模式。例如,Spring的Bean生命周期管理和依赖注入特性可以用于实现自定义的对象池。此外,Spring也提供了与一些常见对象池(如数据库连接池)的集成。

JDBC对象池示例

对象池模式类似于办公室仓库。当新员工被雇佣时,办公室经理需要为他准备工作空间。她会检查办公室仓库是否有备用设备。如果有,她就使用它。如果没有,她就会从亚马逊订购新设备。如果员工被解雇,他的设备会被移动到仓库,以备新工作场所需要时使用。
在这里插入图片描述
第1步
创建一个 ObjectPool 类,用于创建对象的数量。

public abstract class ObjectPool<T> {

    private long expirationTime;
    private ConcurrentHashMap<T, Long> locked, unlocked;

    public ObjectPool() {
        expirationTime = 30000; // 30 秒
        locked = new ConcurrentHashMap<T, Long>();
        unlocked = new ConcurrentHashMap<T, Long>();
    }

    protected abstract T create();
    public abstract boolean validate(T o);
    public abstract void expire(T o);

    public synchronized T checkOut() {
        long now = System.currentTimeMillis();
        T t;
        if (unlocked.size() > 0) {
            Enumeration<T> e = unlocked.keys();
            while (e.hasMoreElements()) {
                t = e.nextElement();
                if ((now - unlocked.get(t)) > expirationTime) {
                    // 对象已过期
                    unlocked.remove(t);
                    expire(t);
                    t = null;
                } else {
                    if (validate(t)) {
                        unlocked.remove(t);
                        locked.put(t, now);
                        return t;
                    } else {
                        // 对象验证失败
                        unlocked.remove(t);
                        expire(t);
                        t = null;
                    }
                }
            }
        }
        // 无可用对象,创建一个新的
        t = create();
        locked.put(t, now);
        return t;
    }

    public synchronized void checkIn(T t) {
        locked.remove(t);
        unlocked.put(t, System.currentTimeMillis());
    }

}

第2步
创建一个实现类,用于获取jdbc连接。

public class JDBCConnectionPool extends ObjectPool<Connection>{

    private String dsn, usr, pwd;

    public JDBCConnectionPool(String driver, String dsn, String usr, String pwd) {
        super();
        try {
            Class.forName(driver).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.dsn = dsn;
        this.usr = usr;
        this.pwd = pwd;
    }

    @Override
    protected Connection create() {
        try {
            return DriverManager.getConnection(dsn, usr, pwd);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void expire(Connection o) {
        try {
            ((Connection) o).close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean validate(Connection o) {
        try {
            return !((Connection) o).isClosed();
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

}

第三步
测试类允许应用程序借用和归还数据库连接:

public class Main {

    public static void main(String args[]) {
        // 做一些事情...

        // 创建 ConnectionPool:
        JDBCConnectionPool pool = new JDBCConnectionPool(
                "org.hsqldb.jdbcDriver", "jdbc:hsqldb://localhost/mydb",
                "sa", "secret");

        // 获取一个连接:
        Connection con = pool.checkOut();

        // 使用连接

        // 归还连接:
        pool.checkIn(con);
    }

}

这个示例展示了如何使用对象池模式管理和重用数据库连接,以优化资源使用和提高性能。

代码地址

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

小结

至此,创建型的6种设计模式的总结完成,感兴趣的同学可以看看之前的博客。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1273661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机体系结构----流水线技术(三)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----计算机系统结构教程(第二版)张晨曦等 计算机体系结构----流水线技术&#xff08;三&#xff09; 3.1 流水线的基本概念3.1.1 什么是流水线3.1.2 流水线的分类1. 部件级流水线、处理机级流…

图解系列--HTTPS,认证

确保 Web 安全的HTTPS 1.HTTP 的缺点 1.1.通信使用明文可能会被窃听 加密处理防止被窃听 加密的对象可以有这么几个。 (1).通信的加密 HTTP 协议中没有加密机制&#xff0c;但可以通过和 SSL&#xff08;Secure Socket Layer&#xff0c;安全套接层&#xff09;或TLS&#xff…

搭建JMeter分布式压测环境轻松应对

引言 您想要提高您的应用程序的性能吗&#xff1f;想要确保它在高负载下仍然能够正常工作吗&#xff1f;那么&#xff0c;您一定需要一个可靠的性能测试工具来帮助您完成这个任务。 JMeter是一个广泛使用的性能测试工具&#xff0c;但是如果您的测试需求变得更加复杂和庞大&a…

数据结构与算法编程题35

用按层次顺序遍历二叉树的方法&#xff0c;统计树中具有度为1的结点数目。 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct B…

Google Chrome访问出现 NET::ERR_CERT_INVALID

Google Chrome访问出现 NET::ERR_CERT_INVALID然后访问不了当前网站&#xff0c;这个是由于证书失效了&#xff0c;临时解决方式是&#xff1a; 第一种方案&#xff1a; 在Chrome提示“您的连接不是私密连接”页面的空白区域点击一下&#xff0c;然后输入“thisisunsafe”(页…

[CustomMessages] section

[CustomMessages] section用来定义自定义的一些{cm:}常量. 一个定义和使用的例子。 [CustomMessages] CreateDesktopIconCreate a &desktop icon[Tasks] Name: desktopicon; Description: "{cm:CreateDesktopIcon}"CustomMessages是支持带参数的&#xff0c;从…

「Verilog学习笔记」状态机-重叠序列检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 读入数据移位寄存&#xff0c;寄存后的数据与序列数做对比&#xff0c;相等则flag为1&#xff0c;不等则为0 timescale 1ns/1nsmodule sequence_test2(input wire clk ,in…

Ascend C 算子开发遇到的问题及解决方法

摘要&#xff1a;在学习Ascend C算子开发进阶课程的时候&#xff0c;进行Ascend C自定义算子工程、算子调用等实验&#xff0c;在开发环境中遇到了一些问题&#xff0c;在这里记录一下。 首先如果在启智社区CANN版本为6.3 &#xff0c;要进行Ascend C算子开发&#xff0c;需要…

TA-Lib学习研究笔记——Volume Indicators (四)

TA-Lib学习研究笔记——Volume Indicators &#xff08;四&#xff09; 1.AD Chaikin A/D Line 量价指标 函数名&#xff1a;AD 名称&#xff1a;Chaikin A/D Line 累积/派发线&#xff08;Accumulation/Distribution Line&#xff09; 简介&#xff1a;Marc Chaikin提出的一…

C++ 学习之匿名名字空间的使用细节

匿名命名空间&#xff08;anonymous namespace&#xff09;是C中的一种特殊命名空间&#xff0c;它没有显式的名称。匿名命名空间可以用来定义仅在当前文件中可见的全局变量、函数和类。 由于没有名字&#xff0c;所以相当于直接引入&#xff0c;但是没有引入定义 如果发生冲…

Influx集群解决方案(Influx Proxy篇)

InFluxDB 集群搭建 本次搭建使用influx proxy 介绍 github地址:https://github.com/chengshiwen/influx-proxy/ Influx Proxy 是一个基于高可用、一致性哈希的 InfluxDB 集群代理服务&#xff0c;实现了 InfluxDB 高可用集群的部署方案&#xff0c; 具有动态扩/缩容、故障恢复…

JRT和检验共用的打印层实现

之前对接的打印和导出是C#实现的&#xff0c;如果要完全Java化就需要用Java把打印元素绘制协议用Java实现&#xff0c;这次介绍实现主体搭建&#xff0c;最终使JRT达到完全信创和跨平台目标。到这篇后&#xff0c;所有的Java难题都解决完毕&#xff0c;几天到几周之内就可以把打…

Echarts大屏可视化_04 横向柱状图模块的引入和开发

模块的引入 1.寻找官方示例引入 ECharts官方实例入口 2.引入示例 ECharts 示例 可从这里直接进入 标题、提示信息、图例都不需要所以直接删掉 <div class"column"><div class"panel bar2"><h2>柱状图-技能掌握</h2><div cla…

项目动态 | 十一月重点上线项目集锦

武清联创商会 【应用场景】商协会资源对接服务平台&#xff1b; 【核心功能】 l 利用资源对接系统&#xff0c;用户可在平台内发布自己的人脉信息、个性化标签&#xff0c;通过对接获得收益&#xff0c;实现人脉增值&#xff1b; l 利用信息发布系统&#xff0c;用户可直观…

UEFI与ESKII源代码分析

这是一本未出版的电子书&#xff0c;是UEFI BIOS从业者的非常重要的参考书籍。需要的朋友可以联系我。

微服务实战系列之EhCache

前言 书接前文&#xff0c;继续深耕。上一篇博主对Redis进行了入门级介绍&#xff0c;大体知道了Redis可以干什么以及怎么使用它。 今日博主继续带着大家学习如何使用EhCache&#xff0c;这是一款基于Java的缓存框架。 微服务实战系列之Redis微服务实战系列之Cache微服务实战…

主成分分析例题 (多元统计分析期末复习)

例一 给定X的协差阵&#xff0c;对其进行主成分分析, &#xff08;1&#xff09;求出每个主成分的贡献率&#xff1b; &#xff08;2&#xff09;求出每个原始变量的信息提取率&#xff1b; 解&#xff1a;对于主成分分析的题&#xff0c;一般来说&#xff0c;题目给定一个协方…

mybatis关于namespace以及id以及Mapper接口命名的说明(了解)

1、建库建表 CREATE DATABASE mybatis-example;USE mybatis-example;CREATE TABLE t_emp(emp_id INT AUTO_INCREMENT,emp_name CHAR(100),emp_salary DOUBLE(10,5),PRIMARY KEY(emp_id) );INSERT INTO t_emp(emp_name,emp_salary) VALUES("tom",200.33); INSERT INTO…

使用Jetty编写RESTful接口

一、依赖 <!--Jetty服务器的核心依赖项&#xff0c;用于创建和管理服务器。--><dependency><groupId>org.eclipse.jetty</groupId><artifactId>jetty-server</artifactId><version>9.4.43.v20210629</version></dependency…

Linux scatterlist 详解

源码基于&#xff1a;Linux 5.4 约定&#xff1a; 芯片架构&#xff1a;ARM64内存架构&#xff1a;UMACONFIG_ARM64_VA_BITS&#xff1a;39CONFIG_ARM64_PAGE_SHIFT&#xff1a;12CONFIG_PGTABLE_LEVELS &#xff1a;3 0. 前言 之前在《Linux DMA... 零拷贝》博文分享了DMA 技…