享元模式
类型:结构型
享元模式通过共享技术实现相同或相似对象的重用,例子可参考常量池
在享元模式中可以共享的相同内容称为 内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为 外部状态(Extrinsic State),其中外部状态和内部状态是相互独立的,外部状态的变化不会引起内部状态的变化。
由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有一些不同的特征,而相同的内部状态是可以共享的。也就是说,享元模式的本质是分离与共享 : 分离变与不变,并且共享不变。把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
在享元模式中通常会出现工厂模式,需要创建一个享元工厂来负责维护一个享元池(Flyweight Pool)(用于存储具有相同内部状态的享元对象)。
在享元模式中,共享的是享元对象的内部状态,外部状态需要通过环境来设置。在实际使用中,能够共享的内部状态是有限的,因此享元对象一般都设计为较小的对象,它所包含的内部状态较少,这种对象也称为细粒度对象。
享元模式的目的就是使用共享技术来实现大量细粒度对象的复用。
角色
- Flyweight: 享元接口,通过这个接口传入外部状态并作用于外部状态;
- ConcreteFlyweight: 具体的享元实现对象,必须是可共享的,需要封装享元对象的内部状态;
- UnsharedConcreteFlyweight: 非共享的享元实现对象,并不是所有的享元对象都可以共享,非共享的享元对象通常是享元对象的组合对象;
- FlyweightFactory: 享元工厂,主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口;
UML
包结构
享元类
接口
package 享元模式.flyWeight;
public interface AbstractColor {
void doOperation(int r,int c);
}
实现类
package 享元模式.flyWeight;
public class Color implements AbstractColor{
private String colorName;
@Override
public void doOperation(int r, int c) {
System.out.println("将颜色:"+this.colorName+"画在("+r+","+c+")上");
System.out.println("该颜色的hashcode为"+this.hashCode());
}
public Color(String colorName){this.colorName=colorName;}
}
生产享元的工厂
package 享元模式.flyWeightFactory;
import 享元模式.flyWeight.AbstractColor;
import 享元模式.flyWeight.Color;
import java.util.HashMap;
public class ColorPool {
private HashMap<String, AbstractColor> hashMap = new HashMap<>();
public AbstractColor get(String colorName){
AbstractColor color = hashMap.get(colorName);
if(color==null){
color = new Color(colorName);
hashMap.put(colorName,color);
}
return color;
}
}
客户端测试
package 享元模式.client;
import 享元模式.flyWeightFactory.ColorPool;
public class Client {
public static void main(String[] args) {
ColorPool colorPool= new ColorPool();
colorPool.get("绿色").doOperation(1,2);
colorPool.get("绿色").doOperation(7,10);
colorPool.get("红色").doOperation(3,4);
colorPool.get("红色").doOperation(10,90);
}
}
效果
可以发现虽然获得了四个享元,但实际上只有两种hashcode,即只有两个不同对象
并且对于同一种对象,进行了不同的操作
将颜色:绿色画在(1,2)上
该颜色的hashcode为356573597
将颜色:绿色画在(7,10)上
该颜色的hashcode为356573597
将颜色:红色画在(3,4)上
该颜色的hashcode为1735600054
将颜色:红色画在(10,90)上
该颜色的hashcode为1735600054
Process finished with exit code 0
优点
- 它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份;
- 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点
- 享元模式使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化;
- 为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。