首页 > 技术文章 > 设计模式(22)-享元模式

guan-li 2018-10-31 10:36 原文


定义

对象的属性通常有共享属性(如岗位,等级,部门)和个性属性(如姓名,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


推荐阅读