定义:
-
享元模式英文称为“Flyweight Pattern”,又译为羽量级模式或者蝇量级模式。
-
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
-
享元模式的主要目的: 是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。
flyweight,运用共享技术有效的支持大量细粒度的对象。享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时就将他们传递进来,就可以通过共享大幅度地减少单个实例的数目。
结构图:
实例:(用户类,用于网站的客户账号,是网站类的外部状态)
内部状态与外部状态:
在享元对象内部并且不会随着环境改变而改变的共享部分,可以称为享元对象的内部状态,而随环境改变而改变的、不可以共享的状态就是外部状态了。
享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了结构参数外基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来就可以通过共享大幅度地减少单个实例的数目。
也就是说,享元模式Flyweight执行时所需要的状态是有内部的也可能有外部的,内部状态存储于ConcreteFlyweigt对象之中,而外部对象则应该考虑由客户端对象存储或计算,当调用Flyweight对象的操作时,将该状态传递给它。
优点:
-
大大减少对象的创建
-
降低系统的内存
-
使效率提高
缺点:
-
提高了系统的复杂度,需要注意分离出外部状态和内部状态。
-
需要关注线程安全性问题
适用场景:
如果一个应用程序使用了大量的相似对象,而这些对象造成了很大的存储开销就应该考虑使用;
还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
需要池化的场景
应用:
说到享元模式,第一个想到的应该就是池化思想了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。
-
String常量池
-
数据库连接池
-
线程池
-
缓冲池
(享元模式的主要目的: 是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用)
享元模式与单例模式的异同:
单例模式和享元模式都是为了避免重复创建对象,但是其本质是不一样的:
-
其实现方式不一样,单例是一个类只有一个唯一的实例,而享元可以有多个实例,只是通过一个共享容器来存储不同的对象。
-
其使用场景不一样,单例是强调减少实例化提升性能,因此一般用于一些需要频繁创建和销毁实例化对象或创建和销毁实例化对象非常消耗资源的类中,如连接池、线程池。而享元则是强调共享相同对象或对象属性,节约内存使用空间。