设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)
- 为什么要用享元模式
- 内部状态与外部状态
- 应用场景
- 场景举例
- 总结
为什么要用享元模式
有大量对象可复用,在服务端减少接口的调用,在客户端减少内存的占用
内部状态与外部状态
了解享元模式就避不开内部状态与外部状态
内部状态:不随环境的变化而变化,在各个对象间共享
外部状态:随环境的改变而改变,由客户端传入
举例说明,在五子棋中,棋子的颜色就是内部状态,只有黑白两色,落子位置(坐标)是外部状态,每次位置都不一样
如果每一个棋子都是一个对象的话,一个棋盘可以放两三百个对象,极大的浪费内存空间,但如果使用享元模式,则可以很好的解决对象的开销问题
应用场景
数据库连接池,String常量池,缓冲池
比如在Integer的源码中有
1 2 3 4 5 6 7 8 9 10
| static final Integer cache[]; static{ cache = new Integer[(high - low) + 1]; } public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
|
场景举例
按照棋子举例,类图比较简单就不画了
抽象接口
1 2 3
| public interface Chess { void draw(int x, int y); }
|
黑白棋
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class BlackChess implements Chess { private final String COLOR = "黑";
@Override public void draw(int x, int y) { System.out.println(COLOR + "棋子落在("+x+","+y+")处"); } } public class WhiteChess implements Chess { private final String COLOR = "白";
@Override public void draw(int x, int y) { System.out.println(COLOR + "棋落在("+x+","+y+")处"); } }
|
对象工厂
1 2 3 4 5 6 7 8 9 10 11 12
| public class ChessFactory { private static final Map<String,Chess> chessMap = new HashMap<>();
public static Chess getChess(String color) { Chess chess = chessMap.get(color); if (chess == null) { chess = "黑".equals(color) ? new BlackChess() : new WhiteChess(); chessMap.put(color,chess); } return chess; } }
|
调用
1 2 3 4 5 6 7 8 9 10 11 12
| Chess white1 = ChessFactory.getChess("白"); Chess white2 = ChessFactory.getChess("白"); Chess black1 = ChessFactory.getChess("黑"); Chess black2 = ChessFactory.getChess("黑"); white1.draw(1,3); white2.draw(2,4); black1.draw(3,3); black2.draw(2,6); System.out.println(white1.hashCode()); System.out.println(white2.hashCode()); System.out.println(black1.hashCode()); System.out.println(black2.hashCode());
|
结果输出
1 2 3 4 5 6 7 8
| 白棋落在(1,3)处 白棋落在(2,4)处 黑棋子落在(3,3)处 黑棋子落在(2,6)处 21685669 21685669 2133927002 2133927002
|
总结
要区分状态,内部状态不可以从客户端设置,而外部状态必须从客户端设置,该模式可以提高内存使用率