天天看点

《设计模式修炼真经》13 — 享元模式

1、定义

享元模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

享元(Flyweight)模式是池技术的重要实现,是我们平时最常用的设计模式之一,常用于对象缓存复用;

享元模式的定义提出了两个要求:细粒度和共享对象。因为要求细粒度,所以不可避免地会使对象数量多且性质相近,那么就将这些对象的信息分为两个部分:内部状态和外部状态。

内部状态指对象共享出来的信息,存储在享元信息内部,并且不回随环境的改变而改变;

外部状态指对象得以依赖的一个标记,随环境的改变而改变,不可共享;

比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。

2、类图

享元模式的通用类图很简单,如下:

《设计模式修炼真经》13 — 享元模式

享元模式主要包括以下角色:

  • 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入;
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口;
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中;
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象;

3、代码实现

享元模式 的Java代码实现如下:

//抽象享元角色(产品的抽象类)
public abstract class Flyweight {
    //内部状态
    private String intrinsic;
    //外部状态  final防止被内部修改,可以看成是对象的唯一标识,即key
    protected final String Extrinsic;
    //要求享元角色必须接受外部状态
    public Flyweight(String _Extrinsic){
        this.Extrinsic = _Extrinsic;
    }
    //定义业务操作
    public abstract void operate();
    //内部状态的getter/setter
    public String getIntrinsic() {
        return intrinsic;
    }
    public void setIntrinsic(String intrinsic) {
        this.intrinsic = intrinsic;
    }
}
//具体享元角色
public class ConcreteFlyweight1 extends Flyweight{
    //接受外部状态
    public ConcreteFlyweight1(String _Extrinsic){
        super(_Extrinsic);
    }
    //根据外部状态进行逻辑处理
    public void operate(){
        //业务逻辑
    }
}
public class ConcreteFlyweight2 extends Flyweight{
    //接受外部状态
    public ConcreteFlyweight2(String _Extrinsic){
        super(_Extrinsic);
    }
    //根据外部状态进行逻辑处理
    public void operate(){
        //业务逻辑
    }
}

//享元工厂,非常简单,主要功能为从对象容器中拿出对象复用
public class FlyweightFactory {
    //定义一个池容器
    private static HashMap<String,Flyweight> pool= new HashMap<String,Flyweight>();
    //享元工厂
    public static Flyweight getFlyweight(String Extrinsic){
        //需要返回的对象
        Flyweight flyweight = null;
        //在池中没有该对象
        if(pool.containsKey(Extrinsic)){
           flyweight = pool.get(Extrinsic);
        }else{
           //根据外部状态创建享元对象
           flyweight = new ConcreteFlyweight1(Extrinsic);
           //放置到池中
           pool.put(Extrinsic, flyweight);
        }
        return flyweight;
    }
}      

4、特点

优点:

大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能;

缺点:

需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱,增加了系统复杂性;

5、适用场景

享元模式通常适用于以下场景:

  1. 系统中存在大量的相似对象;
  2. 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;
  3. 需要缓冲池的场景;

我的视频课

下面是我录制的一些视频课,欢迎大家围观~

​​​《设计模式修炼真经》​​​ 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结,代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。

本套课程深入介绍了经典的23种设计模式,并加入了自己的感悟,希望大家能够彻底掌握设计模式,写出最好的代码,达到无招胜有招的境界,最终超越这23种设计模式。

​​《彻底搞定JVM》​​​ JVM是Java中重要的也是较难理解的内容;

面试者对JVM的了解程度某种程度上反映了面试者技术深度,所以JVM也是面试时经常考察的内容;

本课程从JVM运行流程、数据运行时区域组成部分、类加载机制、垃圾回收机制、内存模型、常见面试题讲解等角度出发,帮你彻底搞定JVM,拿下心仪Offer;

​​《Android性能优化参考》​​ 本课程包含了Android中的App启动优化、UI优化、内存优化、图片优化、耗电量等常见的性能优化场景,通过学习此课程,你将对整个Android性能优化体系有清晰的认识。

性能优化作为Android高级开发的必备技能,也是大厂面试必考的题目,是体现一个人技术深度最好的试金石。

​​《面试之排序算法》​​ 排序算法是我们面试被问到最多的基础算法,本课程详细介绍了七种排序算法,包括插入排序、选择排序、冒泡排序、谢尔排序、快速排序、堆积排序和二路并归排序。每种算法都详细介绍了核心思想、详细步骤、时间复杂度和代码实现,希望帮助大家深入理解排序算法,搞定面试!

​​《Android HyBrid App开发实战》​​ 本课程为Android HyBrid App开发实战课程,由浅入深,从三种App的历史和特点开始,介绍了Android WebView的使用、Java和JS交互的原生方式、著名的WebView安全漏洞、JSBridge的原理和使用,最后通过一个网上商城的实战综合全部内容,让同学们掌握并深入理解Android HyBrid App开发。

​​《AI导论》​​​ 介绍人工智能AI的诞生历史和到现在为止的不同发展阶段;介绍了AI领域中常见的名词概念和其关系,包括机器学习、深度学习、神经网络结构搜索 NAS、生成对抗网络 GAN等;最后对AI发展做出展望。

本课程属于导论课程,旨在帮助同学们从宏观层面把握AI,建立AI的知识体系。

​​《Java注解精讲》​​​ 本课程详细介绍了Java中的注解机制,包括注解的定义和分类,注解的使用和自定义,注解的源码和架构分析;

本课程语言简单凝练,视频短小精悍,让你一次彻底搞懂Java注解!

​​《Java反射精讲》​​​ 反射是Java中重要的也是较难理解的内容;

本课程从反射的定义、作用、原理和使用出发,全方位帮你彻底搞定反射;

您的点赞是我前进的动力~