当前位置: 首页 > news >正文

设计模式-享元模式、享元模式示例

1、简介

享元模式是运用共享技术有效地最大限度地复用细粒度对象的一种模式。该模式中,以对象的信息状态划分,可以分为内部数据和外部数据。

  • 内部数据是对象可以共享出来的信息,这些信息不会随着系统的运行而改变;
  • 外部数据则是在不同运行时被标记了不同的值。

享元模式一般可以分为三个角色,分别为 Flyweight(抽象享元类)、ConcreteFlyweight(具体享元类)和 FlyweightFactory(享元工厂类)。抽象享元类通常是一个接口或抽象类,向外界提供享元对象的内部数据或外部数据;具体享元类是指具体实现内部数据共享的类;享元工厂类则是主要用于创建和管理享元对象的工厂类。

  • 优点:大大减少对象的创建,降低系统的内存,使效率提高。

  • 缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

  • 使用场景:

    • 系统有大量相似对象。
    • 需要缓冲池的场景。
  • 实际例子

    • String就是享元模式,创建对象如果无放到常量池中,有则直接使用,从而减少重复创建相同值对象,占用内存空间
    • 数据库连接池
    • 线程池

2、示例


/**
 * 享元模式
 */
public class FlyweightDemo {

    public static void main(String[] args) {
        Flyweight fw0 = FlyweightFactory.getFlyweight("a");
        Flyweight fw1 = FlyweightFactory.getFlyweight("b");
        Flyweight fw2 = FlyweightFactory.getFlyweight("a");
        Flyweight fw3 = FlyweightFactory.getFlyweight("b");
        fw1.operation("abc");
        System.out.printf("[结果(对象对比)] - [%s]\n", fw0 == fw2);
        System.out.printf("[结果(内在状态)] - [%s]\n", fw1.getType());
    }
}

/**
 * 抽象享元类
 */
interface Flyweight {
    // 对外状态对象
    void operation(String name);
    // 对内对象
    String getType();
}

/**
 * 具体享元类
 */
class ConcreteFlyweight implements Flyweight {
    private String type;

    public ConcreteFlyweight(String type) {
        this.type = type;
    }

    @Override
    public void operation(String name) {
        System.out.println("类型(内在状态):"+type+",名字(外在):"+name);
    }

    @Override
    public String getType() {
        return type;
    }
}

/**
 * 享元工厂类
 */
class FlyweightFactory {
    //享元池
    private static final Map<String, Flyweight> FLYWEIGHT_MAP = new HashMap<>();

    public static Flyweight getFlyweight(String type) {
        if (FLYWEIGHT_MAP.containsKey(type)) {
            //如果在享元池中存在对象,则直接获取
            return FLYWEIGHT_MAP.get(type);
        } else {
            // 在响应池不存在,则新创建对象, 并放入到享元池
            ConcreteFlyweight flyweight = new ConcreteFlyweight(type);
            FLYWEIGHT_MAP.put(type, flyweight);
            return flyweight;
        }
    }
} 

3、对比单例、原型模式

  • 享元模式可以再次创建对象 也可以取缓存对象

  • 单例模式则是严格控制单个进程中只有一个实例对象

  • 享元模式可以通过自己实现对外部的单例 也可以在需要的使用创建更多的对象

  • 单例模式是自身控制 需要增加不属于该对象本身的逻辑

  • 原型模式中相对new来说,clone少了调用构造函数。如果构造函数中存在大量属性初始化或大对象,则使用clone的复制对象的方式性能会好一些。

相关文章:

  • 过滤器---普通过滤器使用、串联过滤器、局部与全局过滤器
  • Docker安装Redis 7.x单机模式
  • 2022-09-04 C++并发编程(十八)
  • 插入一百万数据的最优解分析和耗时
  • DockerFile的基本知识及利用DockerFile构建镜像
  • Spring(二)
  • 计算机毕业设计ssm+vue基本微信小程序的执法助手平台
  • Java项目--网页版音乐播放器(JQuery前端逻辑)
  • windows service 服务器安装 MySQL
  • springboot+mybatis+mysql+Quartz实现任务调度(定时任务,实现可配置)
  • python简介常考面试题目:python是什么,有什么好处,python2和python3的主要区别
  • SpringCloud Stream消息驱动
  • JVisualVM 中线程状态(运行/休眠/等待/驻留/监视)解析
  • 常识——绳结打折法
  • AVL树的特性和模拟实现
  • Android框架之Volley
  • CODING 缺陷管理功能正式开始公测
  • JavaScript DOM 10 - 滚动
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Java基本数据类型之Number
  • Laravel 菜鸟晋级之路
  • ng6--错误信息小结(持续更新)
  • oldjun 检测网站的经验
  • PaddlePaddle-GitHub的正确打开姿势
  • Terraform入门 - 1. 安装Terraform
  • Vue UI框架库开发介绍
  • Vue学习第二天
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从0实现一个tiny react(三)生命周期
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 简单基于spring的redis配置(单机和集群模式)
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用SAX解析XML
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 小试R空间处理新库sf
  • 译有关态射的一切
  • 阿里云API、SDK和CLI应用实践方案
  • 仓管云——企业云erp功能有哪些?
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #define用法
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (学习日记)2024.01.19
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (转)3D模板阴影原理
  • (转)大型网站的系统架构
  • (转载)(官方)UE4--图像编程----着色器开发