原理图:
享元模式(Flyweight)定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率
在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题:
如果一个应用程序使用了太多的对象, 就会造成很大的存储开销。 特别是对于大量轻量级(细
粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“ a”在文档中出现了100000 次, 而实际上我们可以让这一万个字母“ a” 共享一个对象, 当然因为在不同的位置可能字母“ a” 有不同的显示效果(例如字体和大小等设置不同), 在这种情况我们可以为将对象的状态分为“外部状态”和“ 内部状态”, 将可以被共享(不会变化)的状态作为内部状态存储在对象中, 而外部对象(例如上面提到的字体、 大小等) 我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。
享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式
代码实现
package design.flyweight;
import java.util.HashMap;
/**
* 享元模式,第一个想到的应该就是池技术了,
* String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。
* 比如我们每次创建字符串对象时,都需要创建一个新的字符串对象的话,
* 内存开销会很大,所以如果第一次创建了字符串对象“adam“,下次再创建相同的字符串”adam“时,
* 只是把它的引用指向”adam“,这样就实现了”adam“字符串再内存中的共享
*/
public class FlyweightPattern {
public static void main(String[] args) {
int extrinsic = 22;
Flyweight flyweightX = FlyweightFactory.getFlyweight("X");
flyweightX.operate(++extrinsic);
Flyweight flyweightY = FlyweightFactory.getFlyweight("Y");
flyweightY.operate(++extrinsic);
Flyweight flyweightZ = FlyweightFactory.getFlyweight("Z");
flyweightZ.operate(++extrinsic);
Flyweight flyweightReX = FlyweightFactory.getFlyweight("X");
flyweightReX.operate(++extrinsic);
Flyweight unsharedFlyweight = new UnsharedConcreteFlyweight("X");
unsharedFlyweight.operate(++extrinsic);
}
}
// Flyweight抽象类 所有具体享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
abstract class Flyweight {
//内部状态
public String intrinsic;
//外部状态
protected final String extrinsic;
//要求享元角色必须接受外部状态
public Flyweight(String extrinsic) {
this.extrinsic = extrinsic;
}
//定义业务操作
public abstract void operate(int extrinsic);
public String getIntrinsic() {
return intrinsic;
}
public void setIntrinsic(String intrinsic) {
this.intrinsic = intrinsic;
}
}
// ConcreteFlyweight类 继承Flyweight超类或实现Flyweight接口,并为其内部状态增加存储空间
class ConcreteFlyweight extends Flyweight {
//接受外部状态
public ConcreteFlyweight(String extrinsic) {
super(extrinsic);
}
//根据外部状态进行逻辑处理
@Override
public void operate(int extrinsic) {
System.out.println("具体Flyweight:" + extrinsic);
}
}
// 指那些不需要共享的Flyweight子类
class UnsharedConcreteFlyweight extends Flyweight {
public UnsharedConcreteFlyweight(String extrinsic) {
super(extrinsic);
}
@Override
public void operate(int extrinsic) {
System.out.println("不共享的具体Flyweight:" + extrinsic);
}
}
// 一个享元工厂,用来创建并管理Flyweight对象,主要是用来确保合理地共享Flyweight,
// 当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或创建一个实例
class FlyweightFactory {
//定义一个池容器
private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();
//享元工厂
public static Flyweight getFlyweight(String extrinsic) {
Flyweight flyweight = null;
if (pool.containsKey(extrinsic)) { //池中有该对象
flyweight = pool.get(extrinsic);
System.out.print("已有 " + extrinsic + " 直接从池中取---->");
} else {
//根据外部状态创建享元对象
flyweight = new ConcreteFlyweight(extrinsic);
//放入池中
pool.put(extrinsic, flyweight);
System.out.print("创建 " + extrinsic + " 并从池中取出---->");
}
return flyweight;
}
}
运行结果:
创建 X 并从池中取出---->具体Flyweight:23
创建 Y 并从池中取出---->具体Flyweight:24
创建 Z 并从池中取出---->具体Flyweight:25
已有 X 直接从池中取---->具体Flyweight:26
不共享的具体Flyweight:27
参考文章: