对享元模式的理解

一、场景

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

我理解:享元,共享元数据。
当然了也有其他称呼:缓存、Cache、Flyweight

1、简单的案例

  • “渲染”一片森林,森林由树组成。
@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();
    }
}
memory size: 102

二、通过享元模式实现

1、代码

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();
    }
}
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)在创建对象时,共享享元对象。
public Tree(int x, int y, String name, String color) {
    this.x = x;
    this.y = y;

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

	...
}

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

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值