享元模式

https://zhuanlan.zhihu.com/p/392581561

为什么要用享元模式

有大量对象可复用,在服务端减少接口的调用,在客户端减少内存的占用

内部状态与外部状态

了解享元模式就避不开内部状态与外部状态

内部状态:不随环境的变化而变化,在各个对象间共享

外部状态:随环境的改变而改变,由客户端传入

举例说明,在五子棋中,棋子的颜色就是内部状态,只有黑白两色,落子位置(坐标)是外部状态,每次位置都不一样

如果每一个棋子都是一个对象的话,一个棋盘可以放两三百个对象,极大的浪费内存空间,但如果使用享元模式,则可以很好的解决对象的开销问题

应用场景

数据库连接池,String常量池,缓冲池

比如在Integer的源码中有

 static final Integer cache[]; //定义常量数组
 static{
     //....省略,cache的范围在-128~127之间
     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);
 }

场景举例

按照棋子举例,类图比较简单就不画了

抽象接口

 public interface Chess {
     void draw(int x, int y);
 }

黑白棋

 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+")处");
     }
 }

对象工厂

 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;
     }
 }

调用

 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,3)处
白棋落在(2,4)处
黑棋子落在(3,3)处
黑棋子落在(2,6)处
21685669
21685669
2133927002
2133927002

总结

要区分状态,内部状态不可以从客户端设置,而外部状态必须从客户端设置,该模式可以提高内存使用率

posted @ 2022-06-01 21:58  Nausicaa0505  阅读(47)  评论(0编辑  收藏  举报