享元模式:
- 以共享的方式高效地支持大量细粒度对象
- 有时在大并发大数量多循环的情况下new 了大量一样的对象会占据很多内存,从而导致内存溢出
OutOfMemory
- 享元模式分内蕴状态(不可以改变的状态)和外蕴状态(必须客户端修改,并且不能改变内蕴状态),String类型就使用了享元模式,在JVM里面,每一个String都是唯一的.
享元模式其实就是用的缓存思想,创建太多的对象耗内存,如果这些对象可以分有限的类别,那我们就可以先把这些按此类别存储起来,下次要的时候就直接取就可以了.
注意线程安全问题
解决办法就是尽量创建足够多的对象....
-
上类图
代码示例
- 定一个一个产品的抽象接口,在这个模式里面有没有都无所谓了,不过按套路来还是定一个高大上一点
package com.byedbl.flyweight;
/**
* A FlyWeight
*/
public interface Font {
void setFont(String color, int size);
void getFont();
}
- 实现一个产品
package com.byedbl.flyweight;
/**
* A shared ConcreteFlyweight
*/
public class ConcreteFont implements Font {
private String color;
private int size;
private String key;
public ConcreteFont(String s) {
key = s;
//id = "The char is: " + s;
}
public void setFont(String _color, int _size) {
color = _color;
size = _size;
}
public void getFont() {
System.out.println("String :" + key + "--- color is:" + color + "--- size is:" + size);
}
}
- 创建享元工厂,和一般的工厂不同的是多了个
HashMap
去存储已经创建的产品
package com.byedbl.flyweight; /**
* A Flyweight Factory
*/
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class FontFactory {
private Map<String, Font> charHashTable = new ConcurrentHashMap<>();
public FontFactory() {
}
public Font getFlyWeight(String s) {
if(charHashTable.get(s) != null) {
return (Font)charHashTable.get(s);
} else {
Font tmp = new ConcreteFont(s);
charHashTable.put(s, tmp);
return tmp;
}
}
public Map<String, Font> getFactory() {
return charHashTable;
}
}
- 客户端调用
package com.byedbl.flyweight;
/**
* A test client
*/
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] size = {8, 9, 10, 11, 12};
String[] color = {"FFFFFF", "000000", "FF00FF", "CCCCCC", "111111"};
FontFactory myFontFactory = new FontFactory();
String aString = "A test string";
for(int i = 0; i < aString.length(); i++) {
int j = 0;
j = (int)Math.floor(Math.random()*5);
//System.out.println("j is:" + j + "---" +aString.substring(i, i+1));
myFontFactory.getFlyWeight(aString.substring(i, i+1)).setFont(color[j], size[j]);
}
Map<String, Font> map = myFontFactory.getFactory();
System.out.println("Hash table size is:" + map.size());
for(int i = 0; i < aString.length(); i++) {
((Font)map.get(aString.substring(i, i+1))).getFont();
}
}
}