Flyweight Pattern in Java – Java中的Flyweight模式

最后修改: 2018年 2月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’ll take a look at the flyweight design pattern. This pattern is used to reduce the memory footprint. It can also improve performance in applications where object instantiation is expensive.

在这篇文章中,我们将看一下flyweight设计模式。这种模式被用来减少内存占用。在对象实例化昂贵的应用中,它也可以提高性能。

Simply put, the flyweight pattern is based on a factory which recycles created objects by storing them after creation. Each time an object is requested, the factory looks up the object in order to check if it’s already been created. If it has, the existing object is returned – otherwise, a new one is created, stored and then returned.

简单地说,flyweight模式是基于一个工厂,该工厂通过在创建后存储创建的对象来进行回收。每次请求一个对象时,工厂都会查找该对象,以检查它是否已经被创建。如果已经创建,则返回现有的对象–否则,将创建一个新的对象,储存起来,然后返回。

The flyweight object’s state is made up of an invariant component shared with other similar objects (intrinsic) and a variant component which can be manipulated by the client code (extrinsic).

轻量级对象的状态是由一个与其他类似对象共享的不变成分(内在的)和一个可由客户代码操纵的变体成分(外在的)组成的。

It’s very important that the flyweight objects are immutable: any operation on the state must be performed by the factory.

非常重要的是,flyweight对象是不可改变的:对状态的任何操作都必须由工厂来执行。

2. Implementation

2.实施

The main elements of the pattern are:

该模式的主要内容是。

  • an interface which defines the operations that the client code can perform on the flyweight object
  • one or more concrete implementations of our interface
  • a factory to handle objects instantiation and caching

Let’s see how to implement each component.

让我们看看如何实现每个组件。

2.1. Vehicle Interface

2.1.车辆接口

To begin with, we’ll create a Vehicle interface. Since this interface will be the return type of the factory method we need to make sure to expose all the relevant methods:

首先,我们将创建一个Vehicle接口。由于这个接口将是工厂方法的返回类型,我们需要确保公开所有相关的方法。

public void start();
public void stop();
public Color getColor();

2.2. Concrete Vehicle

2.2.混凝土车辆

Next up, let’s make a Car class as a concrete Vehicle. Our car will implement all the methods of the vehicle interface. As for its state, it’ll have an engine and a color field:

接下来,让我们制作一个汽车类作为具体的车辆。我们的汽车将实现车辆接口的所有方法。至于它的状态,它将有一个引擎和一个颜色域。

private Engine engine;
private Color color;

2.3. Vehicle Factory

2.3.车辆工厂

Last but not least, we’ll create the VehicleFactory. Building a new vehicle is a very expensive operation so the factory will only create one vehicle per color.

最后但并非最不重要的是,我们将创建VehicleFactory。建造一辆新车是一个非常昂贵的操作,所以工厂将只为每一种颜色创造一辆车。

In order to do that, we keep track of the created vehicles using a map as a simple cache:

为了做到这一点,我们使用地图作为一个简单的缓存来跟踪所创建的车辆。

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;
}

Notice how the client code can only affect the extrinsic state of the object (the color of our vehicle) passing it as an argument to the createVehicle method.

请注意,客户端代码只能影响对象的外在状态(我们车辆的颜色),将其作为参数传递给createVehicle方法。

3. Use Cases

3.使用案例

3.1. Data Compression

3.1.数据压缩

The goal of the flyweight pattern is to reduce memory usage by sharing as much data as possible, hence, it’s a good basis for lossless compression algorithms. In this case, each flyweight object acts as a pointer with its extrinsic state being the context-dependent information.

flyweight模式的目标是通过共享尽可能多的数据来减少内存的使用,因此,它是无损压缩算法的一个良好基础。在这种情况下,每个flyweight对象作为一个指针,其外在状态是依赖于上下文的信息。

A classic example of this usage is in a word processor. Here, each character is a flyweight object which shares the data needed for the rendering. As a result, only the position of the character inside the document takes up additional memory.

这种用法的一个典型例子是在文字处理器中。在这里,每个字符都是一个重量级的对象,它共享渲染所需的数据。因此,只有字符在文档中的位置会占用额外的内存。

3.2. Data Caching

3.2.数据高速缓存

Many modern applications use caches to improve response time. The flyweight pattern is similar to the core concept of a cache and can fit this purpose well.

许多现代应用程序使用缓存来提高响应时间。flyweight模式类似于缓存的核心概念,可以很好地满足这一目的。

Of course, there are a few key differences in complexity and implementation between this pattern and a typical, general-purpose cache.

当然,这种模式与典型的、通用的高速缓存在复杂性和实现上有一些关键的区别。

4. Conclusion

4.结论

To sum up, this quick tutorial focused on the flyweight design pattern in Java. We also checked out some of the most common scenarios that involve the pattern.

综上所述,本快速教程主要介绍了Java中的flyweight设计模式。我们还查看了一些涉及该模式的最常见场景。

All the code from the examples is available over on the GitHub project.

所有例子的代码都可以在GitHub项目上找到。