享元模式~

简介: 享元模式~

“享元”我们可以理解为共享元素,比如我们生活中的共享单车,共享充电宝,共享汽车,这样做的目的就是为了提高资源的复用,但对于共享的单车,充电宝等,它的拥有者和创建时间是不相同的,但是它核心的东西都是一致的,那么如果在我们的程序中有很多重复的对象,就会造成很大的内存开销。


在享元模式中,它将元素分为两种状态,一部分是内部状态,例如共享单车,这部分是可以完全被共享的,但是对于共享单车的另一部分资源,比如拥有者和创建时间,这部分信息是由客户端来决定的,谁此时使用,那么这部分的信息就是和谁有关的。


享元模式实现共享的核心是,我们不需要关心外部状态,将核心的资源包围起来共享出去,它内部信息都不会随着环境改变而改变,而外部状态,它会随着环境的改变而改变,这部分信息一定不是由我们自己来保存,共享对象一定不会保存这部分信息,这部分信息由客户端保存,客户端在用的时候,传入到享元对象内部,享元对象内部可以自己做一些处理,去使用或者展示他们,享元模式运用共享技术有效地支持大量细类度[细类度对象是指在某个类别下,具有不同属性或特征的对象,可以看作是对于一个类别的细分]的对象,享元模式最典型的应用就是池技术,比如字符串常量池,数据库连接池,线程池等等,他们都是实现了对共享元素的有效利用,避免去创建大量重复的对象,有效地利用资源。


享元对象的内部状态和环境是没有任何关系的,那么外部状态如何传入呢?方法即为我们在定义享元的时候可以定义一些方法,用于将外部状态传入,这样就实现了一个享元对象既有内部状态,也可以接受外部状态

实例:

1:创建抽象的享元对象

package com.wjr.xiangyaunModel.shared_power_bank;

abstract class PowerBankWeight {//抽象的享元对象
    protected int state=0;//0表示未使用,1表示使用
   abstract void getPowerBank(String username);
    abstract void backPowerBank();
}

2:创建具体的享元对象

package com.wjr.xiangyaunModel.shared_power_bank;

public class LvPowerBankWeight extends PowerBankWeight{
    protected String id;
    public LvPowerBankWeight(String id) {
        this.id=id;
    }

    @Override
    void getPowerBank(String userName) {
        state=1;//表示当前为使用状态
        System.out.println(userName+"正在使用"+id+"号充电宝");

    }

    @Override
    void backPowerBank() {
            state=0;//表示当前为未使用状态
    }
}

3:创建享元对象工厂

package com.wjr.xiangyaunModel.shared_power_bank;

import java.util.HashSet;

public class PowerBankFlyWeightFactory {
    private static PowerBankFlyWeightFactory powerBankFlyWeightFactory=new PowerBankFlyWeightFactory();
    HashSet<LvPowerBankWeight> pool=new HashSet<>();//享元对象池--数据结构不唯一,也可选择TreeSet,如何进行选择需要我们根据需求进行分析

    public static PowerBankFlyWeightFactory getPowerBankFlyWeightFactory(){
        return powerBankFlyWeightFactory;
    }

    public PowerBankFlyWeightFactory() {
        //表示享元对象的数量为3
        for(int i=0;i<3;i++){
            pool.add(new LvPowerBankWeight(i+"号"));
        }
    }
    public  LvPowerBankWeight getPowerBank(){
        for(LvPowerBankWeight lvPowerBankWeight:pool){
            if(lvPowerBankWeight.state==0){
                return lvPowerBankWeight;
            }
        }
        return null;
    }
}
package com.wjr.xiangyaunModel.shared_power_bank;

public class FlyWeightPattern {
    public static void main(String[] args) {
        LvPowerBankWeight lvPowerBankWeight1=PowerBankFlyWeightFactory.getPowerBankFlyWeightFactory().getPowerBank();
        lvPowerBankWeight1.getPowerBank("小学牲");
        lvPowerBankWeight1.backPowerBank();

        LvPowerBankWeight lvPowerBankWeight2=PowerBankFlyWeightFactory.getPowerBankFlyWeightFactory().getPowerBank();
        lvPowerBankWeight2.getPowerBank("中学牲");
//        lvPowerBankWeight2.backPowerBank();

        LvPowerBankWeight lvPowerBankWeight3=PowerBankFlyWeightFactory.getPowerBankFlyWeightFactory().getPowerBank();
        lvPowerBankWeight3.getPowerBank("大学牲");
//        lvPowerBankWeight3.backPowerBank();

        LvPowerBankWeight lvPowerBankWeight4=PowerBankFlyWeightFactory.getPowerBankFlyWeightFactory().getPowerBank();
        lvPowerBankWeight4.getPowerBank("打工人");
        lvPowerBankWeight4.backPowerBank();
    }
}

输出如下所示:

小学牲正在使用1号号充电宝
中学牲正在使用1号号充电宝
大学牲正在使用2号号充电宝
打工人正在使用0号号充电宝

享元模式通过池技术,可以确保内存中相同或相似的对象只保留一份,可以大大节约系统资源,提高系统的性能,享元模式的外部状态相对独立,不会影响内部状态,内外环境分离,使得享元对象可以在不同环境中被共享,因为它将状态区分出来,将外部状态由客户端指定,内部状态自己维护,这样使得它能够在不同环境中进行共享,它的缺点也很明显,因为我们要分离出内外状态,因此程序的逻辑性会比较复杂一点。外部状态都需要客户端传入,这也会影响它的运行时间。

相关文章
|
SQL 双11 流计算
Flink SQL 功能解密系列 —— 流计算“撤回(Retraction)”案例分析
通俗讲retract就是传统数据里面的更新操作,也就是说retract是流式计算场景下对数据更新的处理方式。
|
10月前
|
Shell 定位技术 Android开发
微信号要养多久才稳定?微信怎么定位假位置呢
作为专注社交平台技术研究的开发者,我在过去三年中累计维护过200+企业微信账号矩阵
|
JavaScript 容器
鸿蒙应用开发从入门到入行 - 篇6:数据监听器、滚动、侧滑功能
在本篇文章里,您将掌握监听器、滚动、侧滑等相关内容,助力你开发出更具交互的案例。
313 9
鸿蒙应用开发从入门到入行 - 篇6:数据监听器、滚动、侧滑功能
|
算法 数据可视化 计算机视觉
Python中医学图像处理常用的库
在Python中,医学图像处理常用的库包括:ITK(及其简化版SimpleITK)、3D Slicer、Pydicom、Nibabel、MedPy、OpenCV、Pillow和Scikit-Image。这些库分别擅长图像分割、配准、处理DICOM和NIfTI格式文件、图像增强及基础图像处理等任务。选择合适的库需根据具体需求和项目要求。
715 0
|
传感器 存储 安全
智能包装:食品保鲜与追踪的创新
【10月更文挑战第20天】智能包装通过传感器、微电子和物联网技术,实现实时监测和调节食品环境条件,延长食品保鲜期,确保食品安全。本文探讨其基本原理、技术创新、实际应用及未来趋势,展示其在食品行业中的革命性变化。
1311 5
|
数据处理 Python
Python使用装饰器记录函数执行时间
Python使用装饰器记录函数执行时间
307 0
|
程序员 编译器 数据处理
汇编高手秘籍:解锁性能优化新境界,用汇编语言让你的程序飞起来!
【8月更文挑战第31天】汇编语言作为编程基石,其高效性能备受推崇。尽管现代软件开发更偏爱高级语言,但在性能要求极高的场景下,汇编优化仍不可或缺。本文通过示例代码介绍四种优化技巧:循环展开、寄存器分配、指令重排及SIMD指令使用,显著提升执行效率。同时强调分析性能瓶颈、测试优化效果及保持代码可读性的重要性,助力开发者在关键代码路径上实现性能突破。
1102 0
|
SQL 监控 druid
MySQL连接池DataSource怎么使用?
**摘要:** 本文探讨了数据库连接池在高并发Web应用中的重要性,特别聚焦于阿里巴巴的DruidDataSource。DruidDataSource是一个高效的Java数据库连接池,包含监控、SQL防护和日志功能。文中通过示例展示了如何配置和使用DruidDataSource,包括在Java应用中的直接配置和在Spring Boot中的集成,并提到了启用SQL监控。此外,还分享了设置连接池参数的技巧,如合理设定初始、最大和最小连接数,并强调了定期监控和使用内置监控工具优化性能的重要性。
836 0
|
JavaScript 前端开发 网络架构
Vue基础-搭建Vue运行环境
这篇文章介绍了在Vue.js项目中进行开发环境搭建的关键步骤。包括node.js安装和配置、安装Vue及Vue CLI工具、安装webpack模板、安装vue-router、创建Vue项目等步骤。这篇文章为读者提供了清晰的指南,帮助他们快速搭建Vue.js开发环境,为后续的项目开发奠定基础。
715 0
Vue基础-搭建Vue运行环境
|
存储 缓存 监控
Redis 7.0性能大揭秘:如何优化缓存命中率?
Redis 7.0,这货不仅仅是一个简单的缓存工具,它更是一款高性能的数据结构服务器。现在,大家都知道缓存命中率对性能影响特别大,但怎么优化它呢?
594 1