享元模式是一种通过尽可能多地共享数据来最小化内存使用和对象数量,从而提高性能的设计模式。在享元模式中,如果需要相同数据的多个对象,则共享这些对象而不是创建新的对象,从而提高系统的效率。
其实有很多应用场景,我们日常经常能接触到,但是很多人并不知道这其实是享元模式,如:
字符串池:在Java中,String对象使用了享元模式,通过字符串池的方式共享相同的字符串对象,避免了重复创建。
其实,很多池化技术,如数据库连接池、线程池等,背后都是采用了享元模式来共享对象的。
在服务器端开发中,享元模式也经常被使用,可以用来管理网络连接,避免资源的浪费。
假设我们正在编写一个简单的游戏,这个游戏需要绘制很多小怪兽,每个小怪兽有不同的颜色、形状和属性。为了避免创建太多的怪兽对象占用过多的内存,我们可以使用享元模式来实现。
首先,我们创建一个抽象的怪兽类 Monster,包含所有怪兽共有的属性和方法,例如 draw() 方法来绘制怪兽。
public abstract class Monster {
public abstract void draw();
}
然后,我们创建具体的怪兽类,例如红色怪兽、蓝色怪兽、方形怪兽、圆形怪兽等等。这些怪兽类继承自 Monster 类,并在构造方法中初始化它们特有的属性,例如颜色和形状
public class RedMonster extends Monster {
private String color = "red";
@Override
public void draw() {
System.out.println("Draw a " + color + " monster");
}
}
public class BlueMonster extends Monster {
private String color = "blue";
@Override
public void draw() {
System.out.println("Draw a " + color + " monster");
}
}
public class SquareMonster extends Monster {
private String shape = "square";
@Override
public void draw() {
System.out.println("Draw a " + shape + " monster");
}
}
public class CircleMonster extends Monster {
private String shape = "circle";
@Override
public void draw() {
System.out.println("Draw a " + shape + " monster");
}
}
接下来,我们创建一个工厂类 MonsterFactory 来管理怪兽对象的创建和共享。工厂类维护一个 HashMap 对象,用来存储已经创建的怪兽对象。在获取怪兽对象时,如果该对象已经存在,直接返回已有的对象,否则创建一个新的对象并将其存储到 HashMap 中。这样,我们就可以确保每种属性的怪兽只创建一次,从而实现共享。
import java.util.HashMap;
public class MonsterFactory {
private static final HashMap<String, Monster> monsters = new HashMap<>();
public static Monster getMonster(String key) {
Monster monster = monsters.get(key);
if (monster == null) {
switch (key) {
case "red":
monster = new RedMonster();
break;
case "blue":
monster = new BlueMonster();
break;
case "square":
monster = new SquareMonster();
break;
case "circle":
monster = new CircleMonster();
break;
}
monsters.put(key, monster);
}
return monster;
}
}
这样,我们就可以在游戏中随意创建各种类型的怪兽,但是实际上每个怪兽只会被创建一次,避免了过多的内存占用。