「聊设计模式」之享元模式(Flyweight)
🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!
大家下午好,我是bug菌,今天我们继续聊设计模式。
前言
设计模式是解决复杂问题的最佳实践之一,这些模式都是由经验丰富的程序员在解决问题中总结出来的。享元模式是一种结构型设计模式,旨在通过共享尽可能多的对象来减少内存使用和提高性能。
摘要
享元模式是一个可用于优化重复性的设计模式。如果在应用程序中创建了大量相似的对象,那么可以使用享元模式来减少所需的内存和性能开销。该模式实现了对象的共享,从而减少了内存中对象的数量。也就是说,享元模式允许将对象的状态分为内部状态和外部状态。内部状态存储在享元对象内部,并且在对象创建之后不会发生变化。外部状态由客户端代码传递给享元对象。
享元模式
概念
享元模式是一种结构型设计模式,它通过共享相同或相似的对象来减少内存消耗,提高系统的性能和效率。
在享元模式中,对象分为两类:内部状态和外部状态。内部状态是对象的固有属性,可以被共享;而外部状态则取决于对象的使用环境,不可共享。享元模式将内部状态和外部状态分离,并共享内部状态,从而减少内存中相同状态对象的数量。
典型的享元模式应用场景是在需要大量创建相同或相似对象,且创建和销毁对象的成本较高时,如数据库连接池、线程池等。通过共享已有的对象,减少新对象的创建,可以有效地优化系统性能和资源利用。
结构
享元模式中有以下几个角色:
- 抽象享元(
Flyweight
):享元接口,声明了享元对象的方法。 - 具体享元(
ConcreteFlyweight
):实现抽象享元接口,实现抽象享元的方法,并且需要注意内部状态和外部状态的处理。 - 享元工厂(
FlyweightFactory
):享元工厂用于创建和管理享元对象,它维护一个享元池用于存储已经创建的享元对象,以便重复利用。 - 客户端(
Client
):使用享元工厂创建和管理享元对象。
如下是享元模式的UML类图:
优缺点
优点:
享元模式的优点如下:
- 享元模式可以大大减少内存使用,因为共享对象可以由多个上下文使用。它可以用于缓存那些不经常改变但经常使用的对象,从而提高系统的性能。
- 通过使用享元模式,可以减少对象的数量,从而降低系统的复杂性。
缺点:
享元模式的 缺点如下:
- 实现享元模式需要对系统进行全面分析和重构,这可能会增加系统的开发时间和成本。
- 如果内部状态非常复杂,并且不能分为内部状态和外部状态,那么享元模式将无法提供帮助。
应用场景
享元模式适用于以下场景:
当需要创建大量对象时,使用享元模式可以节省内存和系统资源,提高系统性能。
对象具有可共享的状态,因此可以将这些状态独立出来,让多个对象共享。例如,一个文本编辑器中的字符或字体颜色可以共享,从而减少内存占用。
享元模式可以用于缓存系统中,将经常使用的数据缓存起来,以减少系统的访问压力。
适用于使用少量对象来表示大量数据的情况,例如棋盘游戏中的棋子。
适用于需要合理控制内存使用和对象数量的场合,例如移动设备上的游戏开发。
总之,享元模式适用于需要创建大量相似对象的场景,通过共享对象的状态来减少内存占用,提高系统性能。
模式实现
下面是一个简单的示例代码,展示如何使用享元模式来创建和管理汽车对象。
首先是抽象享元接口:
package com.example.javaDesignPattern.flyweight;
/**
* @author bug菌
* @version 1.0
* @date 2023/9/19 16:15
*/
public interface Car {
void drive(String location);
}
然后是具体享元实现:
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);
}
}
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;
}
}
客户端代码如下所示:
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编译器运行该代码来查看它是否有效。
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");
}
}
执行结果如下:
测试用例代码解析
这段代码展示了工厂方法模式的示例。首先定义了一个Client
类,其中main
方法中创建了三个Car
对象,分别使用了工厂方法CarFactory.getCar()
来获取不同类型的车辆对象。然后分别调用了这些车辆对象的drive
方法来模拟它们载客出行的场景。
值得注意的是,工厂方法CarFactory.getCar()
根据传入的参数来选择要创建的车辆对象的类型。在这个示例中,它接受的参数是字符串类型,对应着两种不同的车辆类型:Sport
和Economy
。如果需要添加更多类型的车辆,只需要在工厂方法中加入对应的逻辑即可。这也是工厂方法模式的优点之一,它使得代码更加灵活,易于扩展。
小结
享元模式是一种结构性设计模式,可用于优化内存使用和性能。通过将对象分为内部状态和外部状态,可以共享已经创建的对象实例。该模式适用于需要创建大量相似对象的应用程序。
附录源码
如上涉及代码均已上传同步在GitHub,提供给同学们参考性学习。
总结
享元模式可以帮助我们优化重复性的代码。它允许我们共享已经创建的相似对象,并且可以显著减少内存使用和性能开销。但是,实现此模式需要对系统进行全面分析和重构。如果可以正确地实现享元模式,那么它将有助于提高系统的性能和扩展性。
☀️建议/推荐你
如果想系统性的全面学习设计模式,建议小伙伴们直接毫无顾忌的关注这个专栏《聊设计模式》,无论你是想提升自己的编程技术,还是渴望更好地理解代码背后的设计思想,本专栏都会为你提供实用的知识和启发,帮助你更好地解决日常开发中的挑战,将代码变得更加优雅、灵活和可维护!
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。
📣关于我
我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。
- 点赞
- 收藏
- 关注作者
评论(0)