( 十四 )、 设计模式 之 享元模式(Flyweight)

( 十四 )、 设计模式 之 享元模式(Flyweight)

 

 

 

1、简介

定义:享元模式(Flyweight Pattern)是一种对象结构型模式,主要用于减少创建对象的数量,以减少内存占用和提高性能。享元模式存储这些共享实例的地方称为享元池(Flyweight Pool),可以避免频繁的创建销毁对象,大幅度减少需要创建的对象数量,避免大量相似类的开销,从而提高系统资源的利用率。一般和单例模式配合使用,将享元工厂声明为一个单例类来池化享元对象。享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式
享元模式的核心思想
分离出不变部分与可变部分,通过共享不变部分来减少对象的创建,从而降低内存消耗和提高性能。这种模式的实现方式是通过将对象的状态分为内部状态和外部状态,内部状态是对象不可变的共享部分,而外部状态是可以改变的独立部分。当多个客户端请求同一个享元对象时,它们实际上共享的是同一个对象,这样就避免了重复创建相同的对象,从而节省了内存空间。同时,享元模式还通过工厂模式来实现对象的创建和管理,通过缓存等技术手段来提高对象的复用效率。

 

2、享元模式的结构

  • 抽象享元角色(AbstractFlyWeight):为具体享元角色规定了必须实现的方法,在Java中可以是抽象类,也可以是接口。
  • 具体享元角色(ConcreteFlyWeight):实现抽象角色定义的方法。
  • 享元工厂角色(FlyWeightFactory):生成AbstractFlyWeight角色的工厂,在工厂中生成的AbstractFlyWeight角色可以实现共享实例。享元工厂提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。
  • 客户端角色(Client):使用FlyWeightFactory来生成AbstractFlyWeight角色。

 

3、实现

/**
 * @Author
 * @ClassName AbstractFlyWeight
 * @Description 抽象享元角色(可以是接口, 也可以是抽象类)
 * @Date 2023/12/16 14:46
 * @Version 1.0
 */
public interface AbstractFlyWeight {

}

/**
 * @Author
 * @ClassName ConcreteFlyWeight
 * @Description 具体享元角色
 * @Date 2023/12/16 14:47
 * @Version 1.0
 */
public class ConcreteFlyWeight implements AbstractFlyWeight {

}


/**
 * @Author
 * @ClassName FlyWeightFactory
 * @Description 享元工厂角色
 * @Date 2023/12/16 14:48
 * @Version 1.0
 */
public class FlyWeightFactory {
    /**
     * 持有一个对象缓冲池
     */
    private static final ConcurrentHashMap<String, AbstractFlyWeight> OBJECT_MAP = new ConcurrentHashMap<>();

    /**
     * 方便测试
     */
//    static {
//        OBJECT_MAP.put("ConcreteFlyWeight", new ConcreteFlyWeight());
//    }

    public static AbstractFlyWeight getObjects(Class<?> cls) throws InstantiationException,
            IllegalAccessException {
        AbstractFlyWeight obj = OBJECT_MAP.get(cls.getSimpleName());
        if (obj == null) {
            obj = (AbstractFlyWeight) cls.newInstance();
            OBJECT_MAP.put(cls.getSimpleName(), obj);
        }
        return obj;
    }
}


/**
 * @Author
 * @ClassName Client
 * @Description 客户端角色
 * @Date 2023/12/16 14:56
 * @Version 1.0
 */
public class Client {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
         FlyWeightFactory.getObjects(ConcreteFlyWeight.class);
    }
}

 

4、享元模式适用场景

  • 需要大量使用相同或相似对象的场景。享元模式通过共享对象来避免重复创建相同的对象,从而降低内存消耗和提高系统性能。
  • 线程池是另一种常见的享元模式应用场景。线程池可以避免频繁地创建和销毁线程对象,从而提高系统的效率和性能。

 

5、享元模式与单例模式的区别
目的不同:单例模式的目的是确保一个类仅有一个实例,而享元模式的目的是通过共享对象来减少内存消耗,提高程序的性能。

 

6、优缺点
优点: 大大减少对象的创建,降低系统的内存,使效率提高。
缺点: 提高了系统的复杂度,需要分离出外部状态和内部状态,否则可能会引起线程安全问题。

 

posted @ 2021-09-05 16:31  邓维-java  阅读(71)  评论(0)    收藏  举报