什么是享元模式
享元模式的概括
享元模式就是一种减少创建对象时内存开销的一种设计模式。适用于多个对象中有重复元素的情况。
享元模式通过共享技术实现相同或相似对象的重用,在逻辑上每一个出现的字符都有一个对象与之对应,然而在物理上它们却共享同一个享元对象,这个对象可以出现在一个字符串的不同地方,相同的字符对象都指向同一个实例,在享元模式中,存储这些共享实例对象的地方称为享元池(Flyweight Pool)。我们可以针对每一个不同的字符创建一个享元对象,将其放在享元池中,需要时再从享元池取出。
享元模式的组成
享元模式由以下4部分组成:
- FlyWeight抽象享元类:通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。
- UnsharedConcreteFlyWeight非共享享元类:不能被共享的子类可以设计为非共享享元类。
- ConcreteFlyWeight具体享元类:为内部状态提供成员变量进行存储。
- FlyWeightFactory享元工厂类:创建并管理享元对象,享元池一般设计为键值对。
享元模式的实现
题目
构造1亿个小球,小球的属性有颜色和坐标位置。
具体实现
我们要实现构造1亿个小球。如果一个小球对应一个单独的对象那必定会消耗我们很多内存,所以这种情况我们要使用享元模式去实现。
BallFlyWeight:
public interface BallFlyWeight {
String getColor();//提供内部状态
void display(OutUnShare a);//展示球所在位置并且设置外部状态
}
OutUnShare外部信息储存类(非共享项元类):
public class OutUnShare {
private int x,y;
public OutUnShare(int x ,int y)
{
this.x=x;
this.y=y;
}
public void setx(int x)
{
this.x=x;
}
public void sety(int y)
{
this.y=y;
}
public int getx()
{
return x;
}
public int gety() {
return y;
}
}
InShare具体享元类:
public class InShare implements BallFlyWeight{
private String color;
public InShare(String color)
{
this.color=color;
}
public String getColor() {
return color;
}
public void display(OutUnShare a) {
System.out.println("Ball's color is "+color);
System.out.println("Ball's location is x = "+a.getx()+"--------y ="+a.gety());
}
}
BallFactory:
public class BallFactory {
//建立享元池,将球的颜色对应的类用map存储起来,用作共享
static Map<String,BallFlyWeight> map=new HashMap<String,BallFlyWeight>();
public static BallFlyWeight getBall(String color) {
if(map.get(color)!=null){
return map.get(color);
}else{
BallFlyWeight cfw=new InShare(color);
map.put(color, cfw);
return cfw;
}
}
}
Client(只跑了1000个):
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] Color={"red","blue","black","yellow"};
for(int i=0;i<=1000;i++)
{
Random ranx= new Random();
int x=ranx.nextInt(1000);
Random rany= new Random();
int y=rany.nextInt(1000);
Random rancolor= new Random();
int col=rany.nextInt(4);
BallFlyWeight ball=BallFactory.getBall(Color[col]);
ball.display(new OutUnShare(x,y));
}
}
}
输出:
Ball’s color is yellow
Ball’s location is x = 34--------y =926
Ball’s color is red
Ball’s location is x = 802--------y =493
Ball’s color is black
Ball’s location is x = 113--------y =649
Ball’s color is yellow
Ball’s location is x = 420--------y =568
总结
优点:
- 极大减少内存中对象的数量。
- 相同或相似的对象内存只保持一份,极大的节约资源,提高系统性能。
- 外部状态相对独立,不影响内部变化。
缺点:
- 模式较复杂,使程序逻辑复杂化。
- 为了节省内存,共享了内部状态,分离出了外部状态,而读取外部状态使运行时间变长。用时间换空间。