• FlyWeight(享元模式)


    享元模式

    内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的对象,我们可以通过享元模式,节省内存.
      
    核心:
    享元模式以共享的方式高效地支持大量细粒度对象的重用。
    享元对象能做到共享的关键是区分了内部状态和外部状态。
    • 内部状态:可以共享,不会随环境变化而改变
    • 外部状态:不可以共享,会随环境变化而改变

    享元模式实现的UML图
    在这里插入图片描述

    享元模式实现:

     (1)Flyweight:抽象享元类,所有具体享元类的超类或者接口,通过这个接口,Flyweight 可以接受并作用于外部专题;
     
     (2)ConcreteFlyweight:具体享元类。指定内部状态,为内部状态增加存储空间。
     
     (3)UnsharedConcreteFlyweight:非共享具体享元类。指出那些不需要共享的Flyweight子类。
     
     (4)FlyweightFactory:享元工厂类,用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    简单实现

    Java语言中,String类型就使用了享元模式。String对象是final类型,对象一旦创建就不可改变,同时JAVA会确保一个字符串常量,在常量池中只能存在一份拷贝。

    	package com.lq.flyWeight;
    	
    	/**
    	 * @author lq
    	 * @PACKAGE_NAME: com.lq.flyWeight
    	 * @CLASS_NAME: Client
    	 * @date 2022/11/8 23:03
    	 * @Description:
    	 */
    	public class Client {
    	
    	    public static void main(String[] args) {
    	        String s1 = "abc";
    	        String s2 = "abc";
    	        String s3 = new String("abc");
    	        String s4 = new String("abc");
    	
    	        System.out.println(s1 == s2);
    	        System.out.println(s1 == s3);
    	        System.out.println(s3 == s4);
    	        //intern 取常量池中的值,虽然对象存在,指定的字符串也是同一块区域
    	        System.out.println(s3.intern() == s1);
    	        System.out.println(s3.intern() == s4.intern());
    	    }
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    打印结果:

    	true
    	false
    	false
    	true
    	true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码实现

    抽象享元类

    	package com.lq.flyWeight;
    
    	/**
    	 * @author lq
    	 * @PACKAGE_NAME: com.lq.flyWeight
    	 * @CLASS_NAME: ChessFlyWeight
    	 * @date 2022/11/8 22:28
    	 * @Description:  抽象享元类
    	 */
    	public interface FlyWeight {
    	
    	    /**
    	     * 用以规定所有具体享元角色需要实现的方法.
    	     */
    	    void operation(String extrinsicState);
    	
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    具体享元类

    	package com.lq.flyWeight;
    	
    	/**
    	 * @author lq
    	 * @PACKAGE_NAME: com.lq.flyWeight
    	 * @CLASS_NAME: ConcreteChess
    	 * @date 2022/11/8 22:29
    	 * @Description: 具体享元类
    	 */
    	public class ConcreteFlyWeight implements FlyWeight {
    	    private String intrinsicState = null;
    	
    	    /**
    	     * 构造函数中内蕴状态作为参数传入.
    	     */
    	    public ConcreteFlyWeight(String intrinsicState) {
    	        this.intrinsicState = intrinsicState;
    	    }
    	
    	    /**
    	     * 外蕴状态作为参数传入方法中,可改变方法的行为,但并不改变对象的内蕴状态.
    	     */
    	    @Override
    	    public void operation(String extrinsicState) {
    	        System.out.println();
    	        System.out.println("内蕴状态:" + intrinsicState);
    	        System.out.println("外蕴状态:" + extrinsicState);
    	        System.out.println("-------------------------");
    	    }
    	
    	    @Override
    	    public String toString() {
    	        return this.intrinsicState;
    	    }
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    享元工厂类

    	package com.lq.flyWeight;
    	
    	import java.util.HashMap;
    	import java.util.Map;
    	
    	/**
    	 * @author lq
    	 * @PACKAGE_NAME: com.lq.flyWeight
    	 * @CLASS_NAME: ChessFlyWeightFactory
    	 * @date 2022/11/8 22:30
    	 * @Description: 享元工厂类
    	 */
    	public class FlyWeightFactory {
    	
    	    // 用来登记和存储已经创建过的享元对象
    	    private Map<String, FlyWeight> flyWeightMap = new HashMap<String, FlyWeight>();
    	
    	    // 采用单例模式
    	    private static FlyWeightFactory flyWeightFactory = new FlyWeightFactory();
    	
    	    // 私有化享元工厂的构造方法
    	    private FlyWeightFactory() {
    	    }
    	
    	    // 获取单例享元工厂的实例
    	    public static FlyWeightFactory getFlyWeightFactory() {
    	        return flyWeightFactory;
    	    }
    	
    	    public FlyWeight getFlyWeight(String intrinsicState) {
    	        FlyWeight flyWeight = flyWeightMap.get(intrinsicState);
    	        if (null == flyWeight) {
    	            flyWeight = new ConcreteFlyWeight(intrinsicState);
    	            flyWeightMap.put(intrinsicState, flyWeight);
    	        }
    	        return flyWeight;
    	    }
    	
    	    public Map<String, FlyWeight> getFlyWeightMap() {
    	        return flyWeightMap;
    	    }
    	
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    	package com.lq.flyWeight;
    	
    	import java.util.Map;
    	
    	/**
    	 * @author lq
    	 * @PACKAGE_NAME: com.lq.flyWeight
    	 * @CLASS_NAME: Main
    	 * @date 2022/11/8 22:31
    	 * @Description:
    	 */
    	public class Main {
    	    public static void main(String[] args) {
    	        FlyWeightFactory flyWeightFactory = FlyWeightFactory.getFlyWeightFactory();
    	        flyWeightFactory.getFlyWeight("A").operation("位置");
    	        flyWeightFactory.getFlyWeight("B").operation("位置");
    	        flyWeightFactory.getFlyWeight("A").operation("位置");
    	
    	        System.out.println("已存储的享元对象个数:" + flyWeightFactory.getFlyWeightMap().size() + "个");
    	        for (Map.Entry<String, FlyWeight> entry : flyWeightFactory.getFlyWeightMap().entrySet()) {
    	            System.out.println(entry.getValue());
    	        }
    	    }
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    结果

    	内蕴状态:A
    	外蕴状态:位置
    	-------------------------
    	
    	内蕴状态:B
    	外蕴状态:位置
    	-------------------------
    	
    	内蕴状态:A
    	外蕴状态:位置
    	-------------------------
    	
    	已存储的享元对象个数:2A
    	B
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    享元模式开发中应用的场景

    享元模式由于其共享的特性,可以在任何“池”中操作,比如:线程池、数据库连接池。 String类的设计也是享元模式

    优点

    1、极大减少内存中对象的数量
    2、相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
    3、外部状态相对独立,不影响内部状态

    缺点

    1、模式较复杂,使程序逻辑复杂化
    2、为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态
    3、使运行时间变长。用时间换取了空间。

  • 相关阅读:
    SQL-Labs46关order by注入姿势
    Linux 进程调度和进程管理
    java udp 接收日志
    Wise 的平台工程 KPI 探索之旅
    计算机毕业设计(附源码)python足球爱好者服务平台
    技术解读倚天 ECS 实例 — Arm 芯片的 Python-AI 算力优化
    【WSN定位】基于matlab灰狼算法优化无线传感器非测距定位【含Matlab源码 2008期】
    【算法竞赛01】leetcode第363场周赛
    1-5 AUTOSAR数据交换文件ARXML
    shiro框架04会话管理+缓存管理+Ehcache使用
  • 原文地址:https://blog.csdn.net/qq_45376284/article/details/127760330