一、享元模式
1、享元模式
享元模式(Flyweight Pattern)是一种结构型模式。主要用于减少创建对象的数量,以减少内存占用和提高性能。主要解决有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
享元模式通过缓冲池的思路来实现,从而减少大量相同数据的产生,这样的数据要求内部状态不易变化,如游戏中的子弹,象棋中的棋子等。如果内部状态容易发生变化,就会很容器造成线程不安全的问题,这样的场景一般不推荐享元模式。
2、实现思路
(1)、定义享元接口。
(2)、编写实现享元接口的实现类。
(3)、编写享元工厂类(缓冲池如HashMap,获取享元对象的方法,其他处理缓冲池对象的方法)
二、代码示例
1、代码示例
获取象棋的棋子信息。一副中国象棋通常有很多棋子,每一个棋子的作用固定不发生变化,棋子存在一定的重复情况,如有多个炮,多个卒等。使用享元模式可以简化重复元素的创建。
// 1、定义享元接口
public interface ChineseChess {
String getType(); // 类型
String getDesc(); // 描述
}
// 2.1、定义享元实现类-马
public class Horse implements ChineseChess{
@Override
public String getType() {
return "马";
}
@Override
public String getDesc() {
return "走日子形状,途径可吃掉其他棋子";
}
}
// 2.2、定义享元实现类-炮
public class Cannon implements ChineseChess{
@Override
public String getType() {
return "炮";
}
@Override
public String getDesc() {
return "走直线,间隔一个棋子打击其他棋子";
}
}
// 3、创建享元工厂
import java.util.HashMap;
import java.util.Map;
public class ChineseChessFactory {
private Map<String, ChineseChess> chessMap = new HashMap<>();
public ChineseChess getChess(String type) {
ChineseChess chess = null;
if (chessMap.keySet().contains(type)) {
chess = chessMap.get(type);
} else {
if ("马".equals(type)) {
chess = new Horse();
} else if ("炮".equals(type)) {
chess = new Cannon();
}
chessMap.put(type, chess);
}
return chess;
}
public void removeChess(String type) {
chessMap.remove(type);
}
}
// 4、测试
public static void main(String[] args) {
ChineseChessFactory chessFactory = new ChineseChessFactory();
ChineseChess chess = chessFactory.getChess("马");
ChineseChess chess2 = chessFactory.getChess("马");
chessFactory.removeChess("马");
ChineseChess chess3 = chessFactory.getChess("马");
System.out.println(chess);
System.out.println(chess2);
System.out.println(chess3);
ChineseChess chess1 = chessFactory.getChess("炮");
System.out.println(chess1);
}
运行结果:
总结:
当一个类内部不易变化,且这种类需要大量的创建和销毁时,可以使用享元模式去优化内存和提升性能。主要套路就3步,创建接口,创建实例,创建工厂。工厂内部通过缓存的方式(HashMap,redis等)保存了已经创建过的对象,再次获取时直接走缓存返回。有点类似单例模式和工厂模式的结合,但是享元又不一定是单例的,所以具体使用还要看场景需要。
学海无涯苦作舟!!!