对享元模式的理解

目录

一、场景

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

	...
}

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

相关推荐
Javatutouhouduan2 小时前
2026Java面试的正确打开方式!
java·高并发·java面试·java面试题·后端开发·java编程·java八股文
JAVA面经实录9173 小时前
Java初级最终完整版学习路线图
java·spring·eclipse·maven
Cat_Rocky4 小时前
k8s-持久化存储,粗浅学习
java·学习·kubernetes
知识领航员4 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
释怀°Believe4 小时前
Spring解析
java·后端·spring
ooseabiscuit5 小时前
Laravel4.x:现代PHP框架的奠基之作
java·开发语言·php
节奏昂6 小时前
【一份基础软件的下载地址和安装地址】
java
没什么本事6 小时前
关于C# panel 添加lable问题 -- 明确X和Y 位置错误
android·java·c#
dhashdoia6 小时前
GPT-5.5 代码开发实战:Codex与Browser Use深度集成与星链4SAPI优化方案
java·数据库·人工智能·gpt·架构
xuhaoyu_cpp_java6 小时前
SpringMVC学习(二)
java·经验分享·笔记·学习·spring