享元模式

软件设计模式
2021-05-17 14:29 · 阅读时长4分钟
小课

享元模式是一种结构型设计模式,在实际开发中用的比较少,它主要用于重复利用对象来减少内存占用,当某种场景下,我们需要大量相似的对象,如果我们每次都新创建对象,那内存消耗将非常大,如果能够考虑重复使用某些对象,那么就能大大减少内存使用。

下面以一个示例来说明享元模式的用法,现在有一个Circle类用于绘制圆形,假设其中Circle的color属性是不可变的,通过构造方法传入,而radius属性可以通过setRadius进行修改。

1public enum Color {
2    Red, Yellow, Blue, Green
3}
4
5public class Circle {
6    private final Color color;
7    private int radius;
8
9    public Circle(Color color) {
10        this.color = color;
11    }
12
13    public void setRadius(int radius) {
14        this.radius = radius;
15    }
16
17    public void draw() {
18        System.out.println("draw circle(color=" + color + ", radius=" + radius + ")");
19    }
20}

现在需求是让我们绘制10万个随机颜色和大小的圆形,最简单的实现是这样的。

for (int i = 0; i < 10e5; i++) {
    Circle circle = new Circle(randomColor());
    circle.setRadius(random());
    circle.draw();
}

很明显这样会创建10万个Circle对象,而且这些对象很相似,它们只有color和radius属性不同,color属性是通过构造参数传入且不可修改,而radius属性可以通过setRadius修改,那么可以将带有不同color属性的Cricle对象缓存下来。

下面创建一个用于缓存和创建Circle的工厂类CircleFactory,它的作用是根据color来获取和缓存Color对象。

1public class CircleFactory {
2    private static final HashMap<Color, Circle> cache = new HashMap<>();
3
4    public static Circle getCircle(Color color) {
5        Circle circle = cache.get(color);
6        if (circle == null) {
7            circle = new Circle(color);
8            cache.put(color, circle);
9        }
10        return circle;
11    }
12}

在遍历绘制图形时,将创建Circle对象改为通过CircleFactory获取。

for (int i = 0; i < 10e5; i++) {
    Circle circle = CircleFactory.getCircle(randomColor());
    circle.setRadius(random());
    circle.draw();
}
总结

享元模式的主要目的就是减少内存的使用,但是同时它也增加了一些额外代码,当我们使用从工厂类获取的缓存对象时,通常还需要将对象的属性数据重置,而且缓存本身也需要消耗一定的资源,所以在有大量重复相似对象的情况才适合使用享元模式。

享元模式Flyweight设计模式