首页 > 其他分享 >享元模式

享元模式

时间:2024-01-18 09:33:05浏览次数:22  
标签:享元 -- 模式 对象 driverName MyDbDriver public

把一些常用且不变的对象保存在一个队列里,每次优先从队列中取,没取到则新创建一个,再将它插入队列以供后续使用

  • 定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效的支持大量细粒度的对象
  • 类型:结构型
  • 适用场景:
    •   常常应用于系统底层的开发,以便解决系统的性能问题
    •   系统有大量相似对象、需要缓冲池的场景
  • 优点:
    •   减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率
    •   减少内存之外的其他资源占用
  • 缺点:
    •   关注内/外部状态、关注线程安全问题
    •   使系统、程序的逻辑复杂化
  • 扩展:
    •   内部状态:在享元对象内部,并且不会随着环境改变而改变的共享部分,也就是外部环境怎么变我都不变,并且这个状态在享元对象内部
    •   外部状态:随着环境改变而改变,这种状态是不能共享的状态,这个状态是记录在享元对象外部的
  • 相关设计模式:
    •   享元模式和代理模式:代理模式是代理一个类,如果生成这个代理类需要花费的资源和时间都比较多,那么就可以使用享元模式来提高程序的处理速度
    •   享元模式和单例模式:容器单例就是享元模式和单例模式的结合
  • 关键代码:用HashMap存储对象。用唯一标识码判断,如果内存中有,则返回这个唯一标识码所标识的对象。

Coding

/**
 * <p>享元模式 -- 抽象父类</p>
 */
public abstract class AbstractFlyWeight {

    /**
     * 模拟不同数据库的连接
     */
    public abstract void connection();
}

/**
 * <p>自定义数据源驱动类</p>
 */
public class MyDbDriver extends AbstractFlyWeight {

    /**
     * 数据源驱动名称 == (对于具体的某个数据源驱动,其参数是固定的,因为无需重复new对象)
     */
    private String driverName;

    public MyDbDriver(String driverName) {
        this.driverName = driverName;
    }

    @Override
    public void connection() {
        System.out.println(driverName + " -- 连接数据库");
    }
}

/**
 * <p>数据源驱动工厂类</p>
 */
public class DbDriverFactory {

    private HashMap<String, MyDbDriver> dbDriverMap;

    private List<MyDbDriver> dbDrivers = new ArrayList<>();

    public DbDriverFactory() {
        dbDriverMap = new HashMap<>();
    }

    public MyDbDriver getDbDriver(String driverName) {

        MyDbDriver dbDriver;
        // 有的话,直接返回驱动对象
        if (dbDriverMap.containsKey(driverName)) {
            System.out.println(driverName + "--> 数据源驱动实例已存在,无需再new,直接返回");
            dbDriver = dbDriverMap.get(driverName);
            this.dbDrivers.add(dbDriver);
            return dbDriver;
        }

        dbDriver = new MyDbDriver(driverName);
        this.dbDriverMap.put(driverName, dbDriver);
        this.dbDrivers.add(dbDriver);
        return dbDriver;
    }

    public int size() {
        return dbDriverMap.size();
    }

    public void showConns() {
        this.dbDrivers.forEach(d -> d.connection());
    }
}

测试

/**
 * <p>享元模式测试</p>
 * <p>
 * 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。
 * 这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
 * 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
 * <p>主要解决</p>
 * 在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,
 * 如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
 */
public class FlyWeightTest {

    public static void main(String[] args) {
        DbDriverFactory factory = new DbDriverFactory();
        // 工厂创建或取我们所需要的
        MyDbDriver driver1 = factory.getDbDriver("mysql");
        MyDbDriver driver2 = factory.getDbDriver("mongodb");
        MyDbDriver driver3 = factory.getDbDriver("mysql");
        MyDbDriver driver4 = factory.getDbDriver("postgresql");
        MyDbDriver driver5 = factory.getDbDriver("oracle");
        MyDbDriver driver6 = factory.getDbDriver("postgresql");
        MyDbDriver driver7 = factory.getDbDriver("mysql");
        System.out.println("================================");
        factory.showConns();
        System.out.println("================================");
        System.out.println("工厂实例集大小:" + factory.size());

    }
}

===========运行结果=============
mysql--> 数据源驱动实例已存在,无需再new,直接返回
postgresql--> 数据源驱动实例已存在,无需再new,直接返回
mysql--> 数据源驱动实例已存在,无需再new,直接返回
================================
mysql -- 连接数据库
mongodb -- 连接数据库
mysql -- 连接数据库
postgresql -- 连接数据库
oracle -- 连接数据库
postgresql -- 连接数据库
mysql -- 连接数据库
================================
工厂实例集大小:4

注意:需要考虑到线程安全问题,可以加同步锁,使用线程安全的Map

UML

 源码中应用

  • java.lang.Integer

valueOf 方法,如果满足添加直接返回cache的对象,如果不是就重新new一个对象:

public static Integer valueOf(int i) {
        // -128 ~ 127
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
测试
public class Test {
    public static void main(String[] args) {
        Integer a = Integer.valueOf(100);
        Integer b = 100;

        Integer c = Integer.valueOf(1000);
        Integer d = 1000;

        System.out.println("a==b:" + (a == b));
        System.out.println("c==d:" + (c == d));
    }
}

=======结果======
a==b:true
c==d:false
  • 思考 ThreadLocal 的应用是否是享元模式?

标签:享元,--,模式,对象,driverName,MyDbDriver,public
From: https://www.cnblogs.com/wangzhilei-src/p/17971771

相关文章

  • 设计模式 经典问题
    目录策略模式和简单工厂模式的区别策略模式的类图为什么采用聚合简单工厂模式的类图为什么采用关联表示策略模式和简单工厂模式的区别策略模式和简单工厂模式是两种不同的设计模式,它们在用途和实现上有所不同。简单工厂模式是一种创建型模式,用于创建特定类型的对象。它通过一......
  • Flink 1.18 Standalone 应用模式部署
    本文基于:FlinkJavaDemo1.下载https://dlcdn.apache.org/flink/flink-1.18.0/flink-1.18.0-bin-scala_2.12.tgz2.解压mkdir/usr/flinktar-zxvf/home/flink-1.18.0-bin-scala_2.12.tgz-C/usr/flink/3.推送端运行netcatnc-lp78784.将Maven的包复制到flink的lib目......
  • Spark-Yarn模式部署
    Spark-Yarn模式部署1.解压缩文件将spark-3.0.0-bin-hadoop3.2.tgz文件上传到linux并解压缩,放置在指定位置。#在/opt/software中tar-zxvfspark-3.0.0-bin-hadoop3.2.tgz-C/opt/modulecd/opt/modulemvspark-3.0.0-bin-hadoop3.2spark2.修改配置文件修改hadoop配......
  • ESXi 主机上配置和管理锁定模式
    要提高ESXi主机的安全性,可以将其置于锁定模式。在锁定模式下,默认情况下,操作必须通过 vCenterServer执行。可以选择正常锁定模式或严格锁定模式,这两种模式提供不同的锁定程度。还可以使用“例外用户”列表。主机进入锁定模式时,例外用户不会丢失其特权。使用“异常用户”列表可添加......
  • 适配器模式
    定义:将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作类型:结构型适用场景:已经存在的类,它的方法和需求不匹配时(方法结果相同或相似)不是软件设计阶段考虑的设计模式,是随着软件维护,由于不同产品、不同厂家造成功能类似而接口不相同情况下的......
  • 华企盾DSC防泄密系统四种加密模式的应用场景
    在当今数字化的时代,企业的核心竞争力往往体现在数据资产上,而数据安全的重要性也日益凸显。数据加密是保护企业核心数据的重要手段,不同的加密模式适用于不同部门与员工,能够更好地平衡数据安全与工作效率。本文将围绕华企盾DSC数据防泄密系统介绍四种加密模式,包括使用场景、好处和可......
  • JavaGuide 设计模式
    JavaGuide设计模式1.软件设计原则设计原则名称简单定义开闭原则对扩展开放,对修改关闭单一职责原则一个类只负责一个功能领域中的相应职责里氏替换原则所有引用基类的地方必须能透明地使用其子类的对象依赖倒置原则依赖于抽象,不能依赖于具体实现接......
  • 2023苹果商务管理模式分发app完全指南
    原文链接https://blog.csdn.net/yichensheng/article/details/130622006 随着苹果对企业级开发证书的管控越来越严格,越来越多的企业级证书到期后,苹果不再予以续约,但是很多app都有企业内部分发需求,不希望自己的应用被公开上架。这时候,我们可以参考苹果官方的建议,使用商务管理模......
  • Java动态代理、AOP和装饰器模式
    面向切面编程AOP-AspectOrientedPrograming,主要用于处理核心业务逻辑外的一些东西,比如日志和缓存。这个“切面”可以理解为在代码的某个地方切一刀,在其中加一些东西。装饰器以日志为例,如果没有使用AOP,那么可以使用装饰来实现类似的代码。我们使用装饰器模式来实现一下在执行......
  • 简单的.NET 8 Web API使用Kafka 发布订阅模式,示例api示例
    简单的.NET8WebAPI使用Kafka发布订阅模式,示例api示例kafka当使用Kafka时,我们需要使用Kafka的客户端库来与Kafka集群进行通信。在.NETCore中,可以使用Confluent.Kafka客户端库来实现与Kafka的集成。首先,我们需要在项目中添加Confluent.Kafka库的引用。首先,使用NuGet包管......