定义
对象的属性通常有共享属性(如岗位,等级,部门)和个性属性(如姓名,id)之分,共享属性的值往往是可以列举出或可预估数量的.为避免对象的大量重复创建造成内存资源的浪费,通可将共享属性单独抽离成对象,而个性属性作为方法中的参数传入.这就是享元模式.
注:设计模式之禅中的举例并不合适,将共享属性和个性属性封装在同一个对象中,一旦对象发生个性属性的set操作,则必然全局可见,发生线程安全问题.
注:从全局map中取出的对象必然是全局共有,所有线程通过get取出的对象为同一个对象.
实例
享元模式应用很常见,如Java中的字符串对象即为享元对象,文档中的字母亦为享元对象.
1.接口
public interface Shape {
public void draw(int x,int y,int r);
}
2.享元对象
public class Circle implements Shape{
//正常考虑下,x坐标,y坐标,r半径都是属性,而享元模式中只将值有限的颜色作为属性
private final String color; //颜色
public Circle(String color){
this.color = color;
}
public String getColor(){
return this.color;
}
@Override
public void draw(int x,int y,int r) {
System.out.println("绘制圆形:颜色为"+color+",x坐标为"+x+",y坐标为"+y+"半径为"+r);
}
}
3.享元工厂
public class CircleFlyweightFactory {
//将颜色属性作为key,具体对象作为value
private final static HashMap<String,Circle> flyweights = new HashMap<String,Circle>();
public static Circle getCircle(String color){
Circle circle = null;
//双重校验,如果对象已存在直接返回对象,如果对象为空,进入同步块再次严谨判定.
if(flyweights.containsKey(color)){
circle = flyweights.get(color);
}else{
synchronized(CircleFlyweightFactory.class){
if(!flyweights.containsKey(color)){
circle = new Circle(color);
flyweights.put(color, circle);
}
}
}
return circle;
}
}
4.运行
public class Client {
public static void main(String[] args) {
Random random = new Random();
String[] colors = {"红色","黄色","蓝色"};
for(int i=0;i<20;i++){
Shape circle = CircleFlyweightFactory.getCircle(colors[random.nextInt(3)]);
circle.draw(random.nextInt(100), random.nextInt(100), random.nextInt(100));
}
}
}
结果:
绘制圆形:颜色为黄色,x坐标为4,y坐标为51,半径为79
绘制圆形:颜色为蓝色,x坐标为44,y坐标为72,半径为36
绘制圆形:颜色为蓝色,x坐标为63,y坐标为10,半径为3
绘制圆形:颜色为红色,x坐标为42,y坐标为25,半径为60
绘制圆形:颜色为蓝色,x坐标为92,y坐标为16,半径为71
绘制圆形:颜色为黄色,x坐标为28,y坐标为61,半径为50
绘制圆形:颜色为红色,x坐标为68,y坐标为28,半径为94
绘制圆形:颜色为黄色,x坐标为89,y坐标为4,半径为35
绘制圆形:颜色为蓝色,x坐标为24,y坐标为46,半径为9
绘制圆形:颜色为蓝色,x坐标为81,y坐标为56,半径为29
绘制圆形:颜色为红色,x坐标为39,y坐标为71,半径为25
绘制圆形:颜色为蓝色,x坐标为52,y坐标为74,半径为13
绘制圆形:颜色为蓝色,x坐标为59,y坐标为6,半径为3
绘制圆形:颜色为黄色,x坐标为27,y坐标为90,半径为22
绘制圆形:颜色为红色,x坐标为50,y坐标为44,半径为87
绘制圆形:颜色为黄色,x坐标为63,y坐标为83,半径为89
绘制圆形:颜色为红色,x坐标为70,y坐标为80,半径为52
绘制圆形:颜色为黄色,x坐标为83,y坐标为80,半径为44
绘制圆形:颜色为红色,x坐标为11,y坐标为48,半径为52
绘制圆形:颜色为红色,x坐标为31,y坐标为48,半径为9