特点
享元模式主要用于复用对象,减少对象数量以节省系统资源、提高性能。属于结构型模式。常见于线程池等技术实现。
代码
享元模式共享内部状态,即相同的那部分。外部状态不能共享,即不同的地方,以围棋的棋子为例:围棋棋子在初始状态下分为黑白2色,当棋子移动到棋盘时,会产生一个坐标。
棋子工厂类
public class ChessPiecesFactory {
private static final Map<Color,WeiQiChessPieces> CHESS_PIECES_MAP = new ConcurrentHashMap<>();
// 获取对象 类似于容器式单例
public WeiQiChessPieces getPieces(Color color){
if (!CHESS_PIECES_MAP.containsKey(color)){
WeiQiChessPieces weiQiChessPieces = new WeiQiChessPieces(color);
CHESS_PIECES_MAP.put(color,weiQiChessPieces);
return weiQiChessPieces;
}
return CHESS_PIECES_MAP.get(color);
}
// 提供一个查看对象数量的方法
public int colorCount(){
return CHESS_PIECES_MAP.size();
}
}
棋子接口类
public interface ChessPieces {
Point moveTo(int x,int y);
}
围棋棋子类
public class WeiQiChessPieces implements ChessPieces{
// 棋子颜色 作为内部状态
private Color color;
public WeiQiChessPieces(Color color) {
this.color = color;
}
@Override
public Point moveTo(int x, int y) {
return new Point(x,y,this);
}
}
坐标类
public class Point {
private int x;
private int y;
private ChessPieces chessPieces;
public Point(int x, int y, ChessPieces chessPieces) {
this.x = x;
this.y = y;
this.chessPieces = chessPieces;
}
}
棋盘类
public class Chessboard {
private final List<Point> list = new ArrayList<>();
public void fill(Point point){
list.add(point);
}
}
测试
@Test
public void testFlyweight(){
ChessPiecesFactory piecesFactory = new ChessPiecesFactory();
Chessboard chessboard = new Chessboard();
WeiQiChessPieces pieces = piecesFactory.getPieces(Color.BLACK);
Point point0 = pieces.moveTo(3, 5);
chessboard.fill(point0);
log.info("pieces: {}",pieces);
WeiQiChessPieces pieces2 = piecesFactory.getPieces(Color.BLACK);
Point point1 = pieces.moveTo(4, 6);
chessboard.fill(point1);
log.info("pieces2: {}",pieces2);
int colorCount = piecesFactory.colorCount();
log.info("colorCount: {}",colorCount);
log.info("棋盘: {}",chessboard);
}
2021-03-18 19:32:26.470 INFO 248968 --- [ main] org.example.singleton.FlyweightTest : pieces: WeiQiChessPieces(color=java.awt.Color[r=0,g=0,b=0])
2021-03-18 19:32:26.472 INFO 248968 --- [ main] org.example.singleton.FlyweightTest : pieces2: WeiQiChessPieces(color=java.awt.Color[r=0,g=0,b=0])
2021-03-18 19:32:26.472 INFO 248968 --- [ main] org.example.singleton.FlyweightTest : colorCount: 1
2021-03-18 19:32:26.472 INFO 248968 --- [ main] org.example.singleton.FlyweightTest : 棋盘: Chessboard(list=[Point(x=3, y=5, chessPieces=WeiQiChessPieces(color=java.awt.Color[r=0,g=0,b=0])), Point(x=4, y=6, chessPieces=WeiQiChessPieces(color=java.awt.Color[r=0,g=0,b=0]))])
从测试代码中看,第一次拿黑色棋子和第二次拿的黑色棋子是一样的,并且容器中对象的数量也没有发生变化。