「聊设计模式」之享元模式(Flyweight)

🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!


前言

设计模式是解决复杂问题的最佳实践之一,这些模式都是由经验丰富的程序员在解决问题中总结出来的。享元模式是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存使用和提高性能。

摘要

享元模式是一个可用于优化重复性的设计模式。如果在应用程序中创建了大量相似的对象,那么可以使用享元模式来减少所需的内存和性能开销。该模式实现了对象的共享,从而减少了内存中对象的数量。也就是说,享元模式允许将对象的状态分为内部状态和外部状态。内部状态存储在享元对象内部,并且在对象创建之后不会发生变化。外部状态由客户端代码传递给享元对象。

享元模式

概念

享元模式是一种结构型设计模式,它通过共享相同或相似的对象来减少内存消耗,提高系统的性能和效率。

在享元模式中,对象分为两类:内部状态和外部状态。内部状态是对象的固有属性,可以被共享;而外部状态则取决于对象的使用环境,不可共享。享元模式将内部状态和外部状态分离,并共享内部状态,从而减少内存中相同状态对象的数量。

典型的享元模式应用场景是在需要大量创建相同或相似对象,且创建和销毁对象的成本较高时,如数据库连接池、线程池等。通过共享已有的对象,减少新对象的创建,可以有效地优化系统性能和资源利用。

结构

享元模式中有以下几个角色:

  • 抽象享元(Flyweight):享元接口,声明了享元对象的方法。
  • 具体享元(ConcreteFlyweight):实现抽象享元接口,实现抽象享元的方法,并且需要注意内部状态和外部状态的处理。
  • 享元工厂(FlyweightFactory):享元工厂用于创建和管理享元对象,它维护一个享元池用于存储已经创建的享元对象,以便重复利用。
  • 客户端(Client):使用享元工厂创建和管理享元对象。

如下是享元模式的UML类图:

优缺点

优点:

享元模式的优点如下:

  • 享元模式可以大大减少内存使用,因为共享对象可以由多个上下文使用。它可以用于缓存那些不经常改变但经常使用的对象,从而提高系统的性能。
  • 通过使用享元模式,可以减少对象的数量,从而降低系统的复杂性。

缺点:

享元模式的缺点如下:

  • 实现享元模式需要对系统进行全面分析和重构,这可能会增加系统的开发时间和成本。
  • 如果内部状态非常复杂,并且不能分为内部状态和外部状态,那么享元模式将无法提供帮助。

模式实现

下面是一个简单的示例代码,展示如何使用享元模式来创建和管理汽车对象。

首先是抽象享元接口:

java 复制代码
package com.example.javaDesignPattern.flyweight;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 16:15
 */
public interface Car {
    void drive(String location);
}

然后是具体享元实现:

java 复制代码
package com.example.javaDesignPattern.flyweight;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 16:15
 */
public class Bike implements Car {
    private String type;

    public Bike(String type) {
        this.type = type;
    }

    @Override
    public void drive(String location) {
        System.out.println("Drive " + type + " bike to " + location);
    }
}
java 复制代码
package com.example.javaDesignPattern.flyweight;

import java.util.HashMap;
import java.util.Map;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 16:16
 */
public class CarFactory {
    private static Map<String, Car> carPool = new HashMap<>();

    public static Car getCar(String type) {
        Car car = carPool.get(type);

        if (car == null) {
            car = new Bike(type);
            carPool.put(type, car);
            System.out.println("Create new car of type " + type);
        }
        return car;
    }
}

客户端代码如下所示:

java 复制代码
package com.example.javaDesignPattern.flyweight;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 16:16
 */
public class Client {
    public static void main(String[] args) {
        Car car1 = CarFactory.getCar("Sport");
        car1.drive("New York");

        Car car2 = CarFactory.getCar("Sport");
        car2.drive("San Francisco");

        Car car3 = CarFactory.getCar("Economy");
        car3.drive("Los Angeles");
    }
}

在客户端代码中,我们使用工厂方法来创建汽车对象。如果工厂已经创建了某种类型的汽车,则从享元池中返回汽车对象。否则,它将创建一个新的汽车对象,并将其添加到享元池中。

代码方法介绍

Car

  • drive(String location) 方法:驾驶汽车到指定的位置。

Bike

  • Bike(String type) 构造方法:创建具体享元对象。
  • drive(String location) 方法:驾驶自行车到指定的位置。

CarFactory

  • getCar(String type) 方法:从享元池中获取指定类型的汽车对象。

Client

  • main(String[] args) 方法:客户端代码,用于测试享元模式。

测试用例

下面是测试代码,用于测试享元模式是否工作正常。您可以在本地使用Java编译器运行该代码来查看它是否有效。

java 复制代码
public class Client {
    public static void main(String[] args) {
        Car car1 = CarFactory.getCar("Sport");
        car1.drive("New York");

        Car car2 = CarFactory.getCar("Sport");
        car2.drive("San Francisco");

        Car car3 = CarFactory.getCar("Economy");
        car3.drive("Los Angeles");
    }
}

执行结果如下:

小结

享元模式是一种结构性设计模式,可用于优化内存使用和性能。通过将对象分为内部状态和外部状态,可以共享已经创建的对象实例。该模式适用于需要创建大量相似对象的应用程序。

附录源码

如上涉及代码均已上传同步在GitHub,提供给同学们参考性学习。

总结

享元模式可以帮助我们优化重复性的代码。它允许我们共享已经创建的相似对象,并且可以显著减少内存使用和性能开销。但是,实现此模式需要对系统进行全面分析和重构。如果可以正确地实现享元模式,那么它将有助于提高系统的性能和扩展性。

☀️建议/推荐你

如果想系统性的全面学习设计模式,建议小伙伴们直接毫无顾忌的关注这个专栏《聊设计模式》,无论你是想提升自己的编程技术,还是渴望更好地理解代码背后的设计思想,本专栏都会为你提供实用的知识和启发,帮助你更好地解决日常开发中的挑战,将代码变得更加优雅、灵活和可维护!

📣关于我


我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。

相关推荐
徐*红12 分钟前
java 线程池
java·开发语言
尚学教辅学习资料12 分钟前
基于SSM的养老院管理系统+LW示例参考
java·开发语言·java毕设·养老院
2401_8576363912 分钟前
计算机课程管理平台:Spring Boot与工程认证的结合
java·spring boot·后端
1 9 J14 分钟前
Java 上机实践4(类与对象)
java·开发语言·算法
Code apprenticeship14 分钟前
Java面试题(2)
java·开发语言
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
憨子周1 小时前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
霖雨3 小时前
使用Visual Studio Code 快速新建Net项目
java·ide·windows·vscode·编辑器
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
Fiercezm3 小时前
JUC学习
java