一、定义
享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。
二、使用场景
我们在需要创建大量的相似的对象时,使用享元模式。
享元模式在真正的应用中用的要比较少,一般是一些底层数据结构使用到。
三、角色分析
享元工厂(Flyweight Factory):一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight是,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。
抽象享元(Flyweight):所有具体享元的超类和接口,通过这个接口,Flyweight可以接受并作用于外部状态。
具体享元(Concrete Flyweight):继承Flyweight超类或实现Flyweight接口,并为内部状态增加存储空间。
非共享具体享元(Unshared Concrete Flyweight):指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但他并不强制共享。
四、代码示例
玩家接口:
public interface Player {
void assignWeapon(String weapon);
}
恐怖分子:
public class Terrorist implements Player{
private final String task;
private String weapon;
public Terrorist() {
task = "放置炸弹";
}
@Override
public void assignWeapon(String weapon) {
this.weapon = weapon;
}
@Override
public String toString() {
return "恐怖分子{" +
"task='" + task + '\'' +
", weapon='" + weapon + '\'' +
'}';
}
}
反恐精英:
public class CounterTerrorist implements Player{
private final String task;
private String weapon;
public CounterTerrorist() {
task = "放置炸弹";
}
@Override
public void assignWeapon(String weapon) {
this.weapon = weapon;
}
@Override
public String toString() {
return "反恐精英{" +
"task='" + task + '\'' +
", weapon='" + weapon + '\'' +
'}';
}
}
玩家工厂:
public class PlayerFactory {
private static HashMap<String, Player> hm = new HashMap<>();
public static Player getPlayer(String playerType) {
Player p = null;
if (hm.containsKey(playerType)) {
p = hm.get(playerType);
} else {
switch (playerType) {
case "Terrorist":
p = new Terrorist();
System.out.println("恐怖分子已创建");
break;
case "CounterTerrorist":
p = new CounterTerrorist();
System.out.println("反恐精英已创建");
break;
default:
System.out.println("无此玩家类型");
}
hm.put(playerType, p);
}
return p;
}
}
CS客户端:
public class CounterStrike {
private static String[] playerType = {"Terrorist", "CounterTerrorist"};
private static String[] weapon = {"AK-47", "Maverick", "Gut Knife", "Desert Eagle"};
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Player p = PlayerFactory.getPlayer(getPlayerType());
p.assignWeapon(getWeapon());
System.out.println(p.toString());
}
}
private static String getPlayerType() {
Random r = new Random();
int i = r.nextInt(playerType.length);
return playerType[i];
}
private static String getWeapon() {
Random r = new Random();
int i = r.nextInt(weapon.length);
return weapon[i];
}
}
输出:
恐怖分子已创建
恐怖分子{task='放置炸弹', weapon='Maverick'}
反恐精英已创建
反恐精英{task='放置炸弹', weapon='AK-47'}
恐怖分子{task='放置炸弹', weapon='AK-47'}
反恐精英{task='放置炸弹', weapon='Gut Knife'}
恐怖分子{task='放置炸弹', weapon='Desert Eagle'}
反恐精英{task='放置炸弹', weapon='Desert Eagle'}
恐怖分子{task='放置炸弹', weapon='Gut Knife'}
恐怖分子{task='放置炸弹', weapon='AK-47'}
反恐精英{task='放置炸弹', weapon='Gut Knife'}
反恐精英{task='放置炸弹', weapon='AK-47'}
五、优缺点
优点
1、可以极大地减少内存中对象的数量,使得相同对宁或相似对象在内存中只保存一份。
2、外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。
缺点
1、使得系统更加复杂,需要分离出内部状态和外部状态。
总结
享元模式使用共享技术有效地支持大量细粒度的对象,减少内存中对象的数量。
享元模式有内部状态和外部状态,内部状态可以共享,外部状态作为参数传入。