什么是享元模式?
运用共享技术有效地支持大量细粒度的对象。重用现有的同类对象,如果未找到匹配的对象,则创建新对象。主要用于减少创建对象的数量,以减少内存占用和提高性能。
适用场景
代码实现
示例:围棋,围棋的棋子可以简化为两个对象,黑棋和白棋,不同的是棋子的坐标。
/**
* 棋子
*/
class Piece {
protected Color color;//颜色
protected int x;//x坐标
protected int y;//y坐标
public Piece(Color color, int x, int y) {
this.color = color;
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "棋子:" + color + ",横坐标:" + x + ",纵坐标:" + y;
}
}
/**
* 枚举 棋子类型
*/
enum Color {
Black,
White;
}
/**
* 棋子工厂类,实现对象共享
*/
class PieceFactory {
private static final Map<Color, Piece> map = new ConcurrentHashMap<>();
public synchronized static Piece getPiece(@NotNull Color color, int x, int y) {
Piece piece = map.get(color);
if (null == piece) {
piece = new Piece(color, x, y);
map.put(color, piece);
}
System.out.println("内存占用:" + map.size());
return piece;
}
}
/**
* 组合模式测试
*/
public class FlyweightPattern {
public static void main(String[] args) {
//模拟棋盘 100*100
final int width = 100;
final int high = 100;
//随机获取一百个棋子
final int count = 100;
//两个线程 模拟两个人对弈
//对弈者1
new Thread(() -> {
Random random = new Random();
for (int i = 0; i < count; i++) {
int x = random.nextInt(width);
int y = random.nextInt(high);
Piece piece = null;
//利用奇数偶数模拟黑白棋子
if (i % 2 != 0) {//奇数 白棋
piece = PieceFactory.getPiece(Color.White, x, y);
} else {
piece = PieceFactory.getPiece(Color.Black, x, y);
}
System.out.println(piece);
}
}).start();
//对弈者2
new Thread(() -> {
Random random = new Random();
for (int i = 0; i < count; i++) {
int x = random.nextInt(width);
int y = random.nextInt(high);
Piece piece = null;
//利用奇数偶数模拟黑白棋子
if (i % 2 != 0) {//奇数 白棋
piece = PieceFactory.getPiece(Color.White, x, y);
} else {
piece = PieceFactory.getPiece(Color.Black, x, y);
}
System.out.println(piece);
}
}).start();
//输出:
//内存占用:1
//内存占用:1
//棋子:Black,横坐标:43,纵坐标:52
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:White,横坐标:88,纵坐标:68
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//内存占用:2
//棋子:Black,横坐标:43,纵坐标:52
//.....
}
}