享元模式
1. 介绍
享元模式(Flyweight Pattern)
是一种结构型模式。当需要使用某个对象时,享元模式会先去查找是否存在相同的对象,如果存在,就使用已经存在的对象;如果不存在,才会去创建新的对象;这样就可以减少对象的数量,降低内存消耗和提高性能。
简单理解:享元模式和我们的共享单车很像,如果我们需要使用共享单车,我们不需要去购买一辆新的单车,只需要去找一辆共享单车就可以了。
优点:
- 减少对象的数量。如果对象需要消耗恒很多的资源,或者过程很复杂,需要花费较长的时间,使用享元模式无疑会减少对象的创建和对象的数量。
缺点:
- 不是适用所有的情况。如果外部状态有固有化的性质,且随着内部状态的变化而变化,就不能使用享元模式。
2. 例子
我们在一个ShapeFactory中使用一个HashMap来存储不同颜色的圆形,键是圆形的颜色,如果需要的某种颜色的圆在map中存在,就直接将map中该种的颜色的圆形对象返回,否则创建一个新的该种颜色的圆形对象,将其返回后加入到map中。
类图:
Shape接口:
图形接口,圆形(Circle)实现了这个接口。
package flyWeightPattern;
public interface Shape {
public void draw();
}
Circle类:
代表的是圆形,它实现了Shape接口。
package flyWeightPattern;
public class Circle implements Shape {
private int radius;
private int x;
private int y;
private String color;
public Circle(String color) {
this.color = color;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public void draw() {
System.out.println(String.format("半径为%s,圆心为(%s,%s),颜色为%s", radius, x, y, color));
}
public Circle(int radius, int x, int y, String color) {
super();
this.radius = radius;
this.x = x;
this.y = y;
this.color = color;
}
public Circle() {
super();
}
@Override
public String toString() {
return "Circle [radius=" + radius + ", x=" + x + ", y=" + y + ", color=" + color + "]";
}
}
ShapeFactory类:
这个类中使用了一个HashMap来实现享元模式。
package flyWeightPattern;
import java.util.HashMap;
import java.util.Random;
public class ShapeFactory {
private static final HashMap<String, Circle> circleMap = new HashMap<String, Circle>();
public static Circle getCircle(String color) {
Circle circle = circleMap.get(color);
if (circle == null) {
circle = new Circle(color);
circle.setRadius(getRandomInt());
circle.setX(getRandomInt());
circle.setY(getRandomInt());
circleMap.put(color, circle);
}
return circle;
}
public static int getRandomInt() {
Random random = new Random();
return random.nextInt(100);
}
}
测试类:
package flyWeightPattern;
import org.junit.Test;
public class TestJ {
String[] colorList = {"green", "black", "red", "white"};
@Test
public void test1() {
for (int i = 0; i < 10; i++) {
Circle circle = ShapeFactory.getCircle(getRandomColor());
System.out.println(circle.toString());
//从打印的结果可以看出,如果获取在HashMap中存在的颜色的圆,它返回的是在HashMap中以经
//存在的对象,如果获取的圆的颜色在HashMap中不存在,就会新创建一个对象,并将其加入到HashMap中。
//这就是享元模式,大大减少新的对象的创建
}
}
public String getRandomColor() {
return colorList[(int) Math.floor(Math.random()*colorList.length)];
}
}
运行结果:
Circle [radius=67, x=43, y=57, color=black]
Circle [radius=21, x=66, y=51, color=white]
Circle [radius=21, x=66, y=51, color=white]
Circle [radius=21, x=66, y=51, color=white]
Circle [radius=67, x=43, y=57, color=black]
Circle [radius=50, x=25, y=16, color=green]
Circle [radius=58, x=59, y=41, color=red]
Circle [radius=21, x=66, y=51, color=white]
Circle [radius=21, x=66, y=51, color=white]
Circle [radius=67, x=43, y=57, color=black]
3. 总结
享元模式和共享单车很相似,当需要一个对象时,享元模式会首先判断是否存在这种对象,如果存在,就使用这个对象,如果不存在,才会创建新的对象。