对享元模式的理解

目录

一、场景

  • 有时候,一个程序要创建大量相似的对象,例如,游戏中需要渲染很多的子弹,但这些子弹除了位置不同外,其余都相同。
  • 如果我们不将相同的部分抽取出来,迟早会:Out of Memory。
  • 享元模式会将不同对象的相同数据进行缓存以节省内存。

我理解:享元,共享元数据。

当然了也有其他称呼:缓存、Cache、Flyweight

1、简单的案例

  • "渲染"一片森林,森林由树组成。
java 复制代码
@AllArgsConstructor
public class Tree {
    private int x;
    private int y;
    private String name;
    private String color;

    public int memorySize() {
        // int按1个单位估算,String按字符个数估算。
        return 2 + name.length() + color.length();
    }
}

public class Forest {
    private List<Tree> trees;

    public Forest() {
        trees = new ArrayList<>();
    }

    public void addTree(Tree tree) {
        trees.add(tree);
    }

    public void printMemorySize() {
        System.out.println("memory size: " + trees.stream().mapToInt(Tree::memorySize).sum());
    }
}

public class Application {
    public static void main(String[] args) {
        Forest forest = new Forest();
        forest.addTree(new Tree(1, 2, "apple tree", "red"));
        forest.addTree(new Tree(3, 4, "apple tree", "red"));
        forest.addTree(new Tree(5, 6, "apple tree", "red"));
        forest.addTree(new Tree(7, 8, "orange tree", "yellow"));
        forest.addTree(new Tree(9, 10, "orange tree", "yellow"));
        forest.addTree(new Tree(11, 12, "orange tree", "yellow"));
        forest.printMemorySize();
    }
}
bash 复制代码
memory size: 102

二、通过享元模式实现

1、代码

java 复制代码
public class Tree {
    private int x;
    private int y;
    private final TreeType treeType;

    public Tree(int x, int y, String name, String color) {
        this.x = x;
        this.y = y;

        this.treeType = TreeTypeFactory.gotTreeType(name, color);
    }

    public int memorySize() {
        // int按1个单位估算,String按字符个数估算。
        return 2;
    }
}

@AllArgsConstructor
public class TreeType {
    private String name;
    private String color;

    public int memorySize() {
        return name.length() + color.length();
    }
}

public class TreeTypeFactory {
    private static final Map<String, TreeType> treeTypeMap = new HashMap<>();

    public static TreeType gotTreeType(String name, String color) {
        String key = String.format("%s_%s", name, color);
        if (!treeTypeMap.containsKey(key)) {
            treeTypeMap.put(key, new TreeType(name, color));
        }
        return treeTypeMap.get(key);
    }

    public static int memorySize() {
        return treeTypeMap.values().stream().mapToInt(TreeType::memorySize).sum();
    }
}
java 复制代码
public class Application {
    public static void main(String[] args) {
        Forest forest = new Forest();
        forest.addTree(new Tree(1, 2, "apple tree", "red"));
        forest.addTree(new Tree(3, 4, "apple tree", "red"));
        forest.addTree(new Tree(5, 6, "apple tree", "red"));
        forest.addTree(new Tree(7, 8, "orange tree", "yellow"));
        forest.addTree(new Tree(9, 10, "orange tree", "yellow"));
        forest.addTree(new Tree(11, 12, "orange tree", "yellow"));
        forest.printMemorySize();
    }
}

/*
memory size: 42
*/

2、个人思考

  • 初学外观模式时,我惊呼:这也算设计模式?现在学了享元模式,内心已经很平静了:有应用场景的设计模式就是好模式。
  • 享元模式的关键步骤
  • (1)将类中可以共享的数据抽取出一个享元类。
    • Tree类的(name、color)可以被共享,因此抽取为TreeType。
  • (2)在创建对象时,共享享元对象。
java 复制代码
public Tree(int x, int y, String name, String color) {
    this.x = x;
    this.y = y;

    this.treeType = TreeTypeFactory.gotTreeType(name, color);
}  
  • (3)通过工厂模式封装创建享元对象的细节:
java 复制代码
public class TreeTypeFactory {
    private static final Map<String, TreeType> treeTypeMap = new HashMap<>();

	...
}

享元模式只有一个目的: 减少内存消耗。 如果程序没有遇到内存容量不足的问题, 则可以暂时忽略该模式。

相关推荐
爬山算法40 分钟前
Hibernate(85)如何在持续集成/持续部署(CI/CD)中使用Hibernate?
java·ci/cd·hibernate
菜鸟233号1 小时前
力扣647 回文子串 java实现
java·数据结构·leetcode·动态规划
qq_12498707531 小时前
基于Java Web的城市花园小区维修管理系统的设计与实现(源码+论文+部署+安装)
java·开发语言·前端·spring boot·spring·毕业设计·计算机毕业设计
h7ml1 小时前
查券返利机器人的OCR识别集成:Java Tesseract+OpenCV优化图片验证码的自动解析方案
java·机器人·ocr
野犬寒鸦1 小时前
从零起步学习并发编程 || 第五章:悲观锁与乐观锁的思想与实现及实战应用与问题
java·服务器·数据库·学习·语言模型
Volunteer Technology2 小时前
Sentinel的限流算法
java·python·算法
岁岁种桃花儿2 小时前
SpringCloud从入门到上天:Nacos做微服务注册中心
java·spring cloud·微服务
jdyzzy2 小时前
什么是 JIT 精益生产模式?它与传统的生产管控方式有何不同?
java·大数据·人工智能·jit
Chasmれ2 小时前
Spring Boot 1.x(基于Spring 4)中使用Java 8实现Token
java·spring boot·spring
汤姆yu2 小时前
2026基于springboot的在线招聘系统
java·spring boot·后端