😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~
什么是享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在有效地共享对象以减少内存使用和提高性能。该模式通过将对象的部分状态进行共享,以避免创建过多的相似对象,从而节省内存空间。
享元模式适用场景
- 当系统中存在大量相似对象时,可以使用享元模式来减少对象的数量,从而节省内存开销。
- 当对象的大部分状态可以被外部状态替代时,可以将这些外部状态抽取出来共享,而将内部状态作为非共享状态。
- 当需要对大量的细粒度对象进行操作时,使用享元模式可以减少对象的数量,提高系统性能。
常见的使用场景包括
- 字符串池:在字符串处理中,常常使用字符串池来共享相同的字符串,以避免重复创建相同内容的字符串对象。
- 连接池:数据库连接池和线程池是常见的享元模式应用。通过共享数据库连接或线程对象,可以避免频繁地创建和销毁对象,提高系统性能。
- 缓存系统:在缓存系统中,可以使用享元模式来共享缓存对象,以避免重复创建相同的缓存项。
- 图形绘制:在图形绘制中,可以使用享元模式来共享相同的图形对象,从而减少内存开销。
总之,享元模式通过共享对象的部分状态来节省内存空间和提高性能,适用于大量相似对象的场景,特别是当对象的内部状态较少且外部状态可被替代时。
生活案例
假设你是影院的管理者,需要管理和显示大量的座位信息。在这个场景中,可以使用享元模式来优化座位对象的创建和管理。
首先,我们可以创建一个座位类 Seat
,该类包含座位的行号和列号等属性。然后,我们创建一个座位工厂类 SeatFactory
,用于管理和共享座位对象。
在电影开始之前,当有观众购买座位并入场时,你可以根据座位的行号和列号从工厂中获取对应的座位对象。这样,即使有很多观众,但实际上只需要创建一次相同位置的座位对象,然后共享给多个观众使用,从而减少了对象的数量和内存占用。
当电影院当天关门结束营业后后,你可以清理座位工厂,释放座位对象。
通过使用享元模式,你可以在营业期间高效地管理和共享座位对象,避免了大量重复创建相同位置的座位对象,减少了内存开销,提高了系统性能。
这个生活场景中的座位管理就是享元模式的一个应用示例。通过共享相同的座位对象,我们可以有效地管理和优化座位信息,减少对象的数量,提高系统的效率。
案例代码
首先,创建座位类 Seat
:
public class Seat {
private int row;
private int column;
public Seat(int row, int column) {
this.row = row;
this.column = column;
}
public int getRow() {
return row;
}
public int getColumn() {
return column;
}
}
然后,创建座位工厂类 SeatFactory
:
import java.util.HashMap;
import java.util.Map;
public class SeatFactory {
private static Map<String, Seat> seatMap = new HashMap<>();
public static Seat getSeat(int row, int column) {
String key = row + "-" + column;
if (seatMap.containsKey(key)) {
return seatMap.get(key);
} else {
Seat seat = new Seat(row, column);
seatMap.put(key, seat);
return seat;
}
}
public static void clearSeats() {
seatMap.clear();
}
}
在使用场景中,生成和管理座位:
public static void main(String[] args) {
// 生成座位并显示座位信息
Seat seat1 = SeatFactory.getSeat(1, 1);
Seat seat2 = SeatFactory.getSeat(1, 2);
Seat seat3 = SeatFactory.getSeat(2, 1);
Seat seat4 = SeatFactory.getSeat(2, 2);
System.out.println(seat1.getRow() + "-" + seat1.getColumn());
System.out.println(seat2.getRow() + "-" + seat2.getColumn());
System.out.println(seat3.getRow() + "-" + seat3.getColumn());
System.out.println(seat4.getRow() + "-" + seat4.getColumn());
// 从工厂获取座位对象
Seat seat5 = SeatFactory.getSeat(1, 1);
Seat seat6 = SeatFactory.getSeat(1, 2);
System.out.println(seat5.getRow() + "-" + seat5.getColumn());
System.out.println(seat6.getRow() + "-" + seat6.getColumn());
// 清理座位工厂
SeatFactory.clearSeats();
}
在上述代码中,座位工厂类 SeatFactory 使用一个 HashMap 来管理座位对象,通过座位的行号和列号作为键,将座位对象作为值进行存储。当需要获取座位对象时,首先判断工厂中是否已经存在相同位置的座位对象,如果存在,则直接返回该对象;如果不存在,则创建一个新的座位对象,并将其添加到工厂中进行管理。
通过这种方式,我们可以在音乐会期间共享座位对象,避免了重复创建相同位置的座位对象,从而减少了对象的数量和内存占用。
注意:以上代码仅为示例,为了简化代码逻辑,未涉及多线程和线程安全性。在实际应用中,如果存在多个线程并发访问座位工厂,需要考虑线程安全性并进行适当的同步处理。
享元模式优缺点
享元模式的优点:
- 减少内存占用:通过共享对象,减少了系统中的对象数量,从而降低了内存的占用。
- 提高性能:由于减少了对象的创建和销毁,提高了系统的运行效率。
- 简化对象管理:享元模式将共享对象的创建和管理集中在一个工厂类中,简化了对象的管理和维护过程。
享元模式的缺点:
- 引入共享状态:
共享对象需要考虑线程安全性
,特别是在多线程环境下访问共享对象时需要进行同步处理,这会增加系统的复杂性。 - 不适用于所有情况:享元模式适用于有大量相似对象需要共享的场景,如果对象差异较大,共享的效果可能会降低,甚至无法使用享元模式。
结语
本章节主要介绍了享元模式、享元模式适用场景、享元模式的优缺点,并以影院座位的生活场景模拟享元模式的样例代码,如果本文对你有用,欢迎关注收藏评论,后续将陆续推出贴切生活的搞笑讲解方式带大家一起学编程~