对享元模式的理解

目录

一、场景

  • 有时候,一个程序要创建大量相似的对象,例如,游戏中需要渲染很多的子弹,但这些子弹除了位置不同外,其余都相同。
  • 如果我们不将相同的部分抽取出来,迟早会: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<>();

	...
}

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

相关推荐
YuTaoShao1 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张31 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx4 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野4 小时前
【Java|集合类】list遍历的6种方式
java·python·list
二进制person5 小时前
Java SE--方法的使用
java·开发语言·算法
小阳拱白菜6 小时前
java异常学习
java
FrankYoou7 小时前
Jenkins 与 GitLab CI/CD 的核心对比
java·docker
麦兜*7 小时前
Spring Boot启动优化7板斧(延迟初始化、组件扫描精准打击、JVM参数调优):砍掉70%启动时间的魔鬼实践
java·jvm·spring boot·后端·spring·spring cloud·系统架构
KK溜了溜了8 小时前
JAVA-springboot 整合Redis
java·spring boot·redis
天河归来8 小时前
使用idea创建springboot单体项目
java·spring boot·intellij-idea