13、享元模式
说到享元模式,第一个想到的应该就是池技术了,String常量池、数据库连接池、缓冲池等等都是享元模式的应用,所以说享元模式是池技术的重要实现方式。
享元模式是运用共享技术有效的支持大量细粒度的对象。
享元对象能做到共享的关键是区分了内部状态以及外部状态:
- 内部状态:可以共享,不会随环境改变而改变。
- 外部状态:不可以共享,会随环境改变而改变。
享元模式通用UML类图:
具体例子:以围棋为例子,围棋颜色、大小是可以共享的,所以颜色和大小可以称为内部状态,但围棋在棋盘上的位置是不共享的,所以称为外部状态。
UML类图:
Java代码:
public interface IChess {
String getColor();
void display(Location location);
}
// 棋子位置类
public class Location {
private int x;
private int y;
public Location(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
// 白棋
public class WhiteChess implements IChess {
@Override
public String getColor() {
return "白色";
}
@Override
public void display(Location location) {
System.out.println("棋子的位置:(" + location.getX() + "," + location.getY() + ")");
}
}
// 黑棋
public class BlackChess implements IChess {
@Override
public String getColor() {
return "黑色";
}
@Override
public void display(Location location) {
System.out.println("棋子的位置:(" + location.getX() + "," + location.getY() + ")");
}
}
//生产棋子的工厂
public class ChessFactory {
private static HashMap<String, IChess> chessPool = new HashMap<>();
public static IChess getChess(String color) {
if (color.equals("黑色")) { //如果要黑色棋子
IChess iChess = chessPool.get(color);
if (iChess == null) { //黑色棋子不存在,则创建并存入
BlackChess blackChess = new BlackChess();
chessPool.put("黑色", blackChess);
return blackChess;
} else { //黑色棋子存在,直接返回
return iChess;
}
} else if (color.equals("白色")) { //如果要白色棋子
IChess iChess = chessPool.get(color);
if (iChess == null) { //白色棋子不存在,则创建并存入
WhiteChess whiteChess = new WhiteChess();
chessPool.put("黑色", whiteChess);
return whiteChess;
} else { //白色棋子存在,直接返回
return iChess;
}
} else {
return null;
}
}
}
public class Test85 {
public static void main(String[] args) {
IChess blackChess1 = ChessFactory.getChess("黑色");
IChess blackChess2 = ChessFactory.getChess("黑色");
System.out.println(blackChess1==blackChess2);
IChess whiteChess1 = ChessFactory.getChess("白色");
System.out.println(blackChess1.getColor());
System.out.println(whiteChess1.getColor());
blackChess1.display(new Location(10,10));
whiteChess1.display(new Location(5,7));
}
}