1. 概述
在本文中,我们介绍享元设计模式。此模式用于减少内存占用,它还可以提高对象实例化成本高昂的应用程序的性能。
简而言之,享元模式基于一个工厂,该工厂通过在创建后存储它们来回收创建的对象。每次请求一个对象时,工厂都会查找该对象以检查它是否已经创建。如果有,则返回现有对象;否则将创建一个新对象,存储然后返回。
享元对象的状态由一个与其他类似对象共享的不变组件(内在)和一个可以由客户端代码操作的变体组件(外在)组成。
享元对象的不可变性非常重要:对状态的任何操作都必须由工厂执行。
2. 实现
该模式的主要元素是:
- 定义客户端代码可以对享元对象执行的操作的接口
- 我们接口的一个或多个具体实现
- 处理对象实例化和缓存的工厂
接下来让我们看看如何实现每个组件。
2.1 Vehicle接口
首先,我们创建一个Vehicle接口。由于此接口将是工厂方法的返回类型,因此我们需要确保公开所有相关方法:
public void start();
public void stop();
public Color getColor();
2.2 具体的Vehicle实现
接下来,让我们将Car类作为具体的Vehicle。我们的Car将实现Vehicle接口的所有方法,至于它的状态,它将有一个engine和一个color字段:
private Engine engine;
private Color color;
2.3 Vehicle工厂
最后但同样重要的是,我们将创建VehicleFactory。制造一辆新车是一项非常昂贵的操作,因此工厂只会为每种颜色制造一辆汽车。
为此,我们使用Map作为简单缓存来跟踪创建的车辆:
private static Map<Color, Vehicle> vehiclesCache = new HashMap<>();
public static Vehicle createVehicle(Color color) {
Vehicle newVehicle = vehiclesCache.computeIfAbsent(color, newColor -> {
Engine newEngine = new Engine();
return new Car(newEngine, newColor);
});
return newVehicle;
}
请注意,客户端代码只能影响对象的外部状态(车辆的颜色),并将其作为参数传递给createVehicle方法。
3. 用例
3.1 数据压缩
享元模式的目标是通过共享尽可能多的数据来减少内存使用量,因此,它是无损压缩算法的良好基础。在这种情况下,每个享元对象都充当一个指针,其外部状态是上下文相关的信息。
这种用法的一个典型例子是在文字处理器中。在这里,每个角色都是一个享元对象,共享渲染所需的数据。因此,只有字符在文档中的位置会占用额外的内存。
3.2 数据缓存
许多现代应用程序使用缓存来缩短响应时间。享元模式类似于缓存的核心概念,可以很好地满足这个目的。
当然,此模式与典型的通用缓存在复杂性和实现方面存在一些关键差异。
4. 总结
总而言之,本快速教程重点介绍了Java中的享元设计模式,并介绍了一些涉及该模式的最常见场景。
与往常一样,本教程的完整源代码可在GitHub上获得。