对享元模式的理解

目录

一、场景

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

	...
}

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

相关推荐
蓝澈112113 分钟前
迪杰斯特拉算法之解决单源最短路径问题
java·数据结构
Kali_0720 分钟前
使用 Mathematical_Expression 从零开始实现数学题目的作答小游戏【可复制代码】
java·人工智能·免费
rzl0232 分钟前
java web5(黑马)
java·开发语言·前端
guojl1 小时前
深度解读jdk8 HashMap设计与源码
java
guojl1 小时前
深度解读jdk8 ConcurrentHashMap设计与源码
java
爱上语文1 小时前
Redis基础(5):Redis的Java客户端
java·开发语言·数据库·redis·后端
A~taoker1 小时前
taoker的项目维护(ng服务器)
java·开发语言
HGW6892 小时前
基于 Elasticsearch 实现地图点聚合
java·elasticsearch·高德地图
hi星尘2 小时前
深度解析:Java内部类与外部类的交互机制
java·开发语言·交互
wuxinyan1232 小时前
Java面试题033:一文深入了解MySQL(5)
java·数据库·mysql·面试