Skip to content

享元设计模式复用设备厂商对象

概述

主要用于减少创建对象的数量,以减少内存占用和提高性能。提供了减少对象数量从而改善应用所需的对象结构的方式,也就是说如果系统中存在多个相同的对象,那么只需共享一份就可以了,不必每个都去实例化每一个对象,这样来精简内存资源,提升性能和效率。

经常很多人会把缓存混淆,他们实际上是有明显不同的,享元模式要解决的问题是节约内存空间的大小也就是解决空间效率问题,而缓存本质是为了节省时间(解决时间效率,并没用减少对象的创建)

本质上来说,享元模式是通过创建更多的可复用对象的共有特征来尽可能地减少创建重复对象的内存消耗。

使用场景

  1. 一个应用程序使用了大量的相同对象,造成了存储开销。

案例

大健康康养系统中,我们会对接不同厂商的多种设备,在设备上报监测数据的时候,需要将数据补充厂商信息,每上报一条数据后需要创建一个厂商对象,这样就会创建大量的厂商对象,这些对象几乎是不变的,这种就很合适采用享元设计模式复用这些对象

Flyweight 接口

java
public interface Flyweight {

    ManufacturerInfo getInfo();

}

具体 Flyweight 接口实现,存储器内部不可变状态

java
public class ConcreteManufacturerFlyweight implements Flyweight{

    private final ManufacturerInfo manufacturerInfo;

    public ConcreteManufacturerFlyweight(ManufacturerInfo manufacturerInfo) {
       this.manufacturerInfo = manufacturerInfo;
    }

    @Override
    public ManufacturerInfo getInfo() {
        return manufacturerInfo;
    }

}

定义 Flyweight 工厂

java
public class ManufacturerFactory {

    private final Map<String, Flyweight> FLYWEIGHT_POOL = new HashMap<>();

    public Flyweight getManufacturer(String id) {
        if (!FLYWEIGHT_POOL.containsKey(id)) {
            // 假设不存在,去查询下数据库,然后放到FLYWEIGHT_POOL,也可以程序启动的时候就直接加载到内存中,要是查询不到就抛出异常
            ManufacturerInfo manufacturerInfo = new ManufacturerInfo(id, UUID.randomUUID().toString(),UUID.randomUUID().toString().substring(0,8));
            ConcreteManufacturerFlyweight flyweight = new ConcreteManufacturerFlyweight(manufacturerInfo);
            FLYWEIGHT_POOL.put(id,flyweight);
        }
        return FLYWEIGHT_POOL.get(id);
    }

}

测试

java
public class Client {

    public static void main(String[] args) {
        ManufacturerFactory factory = new ManufacturerFactory();
        Flyweight manufacturer = factory.getManufacturer("1");
        ManufacturerInfo manufacturerInfo = manufacturer.getInfo();
        System.out.println(manufacturerInfo);
        Flyweight manufacturer1 = factory.getManufacturer("1");
        ManufacturerInfo manufacturerInfo1 = manufacturer.getInfo();
        System.out.println(manufacturerInfo1);
        System.out.println(manufacturer1.equals(manufacturer));
    }
}

输出

text
ManufacturerInfo(id=1, code=c6ba7f67-3c02-43a3-a385-2c01ed71d7d2, name=75448e4e)
ManufacturerInfo(id=1, code=c6ba7f67-3c02-43a3-a385-2c01ed71d7d2, name=75448e4e)
true

Released under the MIT License.