设计模式:享元模式
享元模式中的享指的共享的意思,该模式以共享的方式支持某些对象的重用(特别是一些大的对象)以此节约空间。典型的是以时间换空间的做法。
例如:java语言中String类型就是使用享元模式。对于JVM来说,String对象都是共享的。如果一个系统中两个String对象所包含的字符串内容相同,jvm
实际上只创建一个String对象提供两个引用。
享元模式一般的角色:
享元工厂类(FlyWeight享元工厂类):管理享元对象
抽象享元类(FlyWeight抽象类):接口或抽象类,向外界提供对象内部状态。
具体享元类(ConcreteFlyWeight):继承自抽象享元类。为内部状态提供成员变量存储。
非共享享元类(UnshareConcreteFlyWeight):不能被共享的一些子类。
享元对象能作为共享的的关键是区分内部状态和外部状态。
内部状态:可以共享。
外部状态:不可以共享。
例子:
描述一个围棋软件,每个棋子是一个对象(颜色,形状等)这些是可以共享的,对应内部状态。只有棋子的位置不是共享的,对应外部状态。
1 2 3 4 5 6 7 8 9 10 | /** * 享元类 */ public interface ChessFlyWeight { //颜色 void setColor(String c); String getColor(); //描述位置 void display(Position c); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class OneChess implements ChessFlyWeight{ //为内部状态提供成员变量存储。 private String color; public OneChess(String color) { super (); this .color = color; } @Override public void display(Position c) { System.out.println( "棋子颜色:" +color); System.out.println( "棋子位置:" +c.getX()+ "----" +c.getY()); } @Override public String getColor() { return color; } @Override public void setColor(String c) { this .color = c; } } |
外部状态位置单独设计一个类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /** * 外部状态UnSharedConcreteFlyWeight * 非共享狀態 */ public class Position { private int x; private int y; public Position( int x, int y) { this .x = x; this .y = y; } public int getX() { return x; } public void setX( int x) { this .x = x; } public int getY() { return y; } public void setY( int y) { this .y = y; } } |
享元工厂类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * 享元工厂类 * 创建和管理享元对象 */ public class ChessFlyWeightFactory { //享元池 private static Map<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>(); public static ChessFlyWeight getChess(String color){ if (map.get(color)!= null ){ return map.get(color); } else { ChessFlyWeight cfw = new OneChess(color); map.put(color, cfw); return cfw; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 | public class Client { public static void main(String[] args) { ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess( "黑色" ); ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess( "黑色" ); System.out.println(chess1 == chess2); System.out.println( "增加位置外部状态" ); chess1.display( new Position( 1 , 12 )); chess2.display( new Position( 50 , 60 )); } } |
使用享元模式一般步骤:
1. 抽象享元对象,内部状态采用享元类处理
2. 外部状态(可变状态,非共享)单独抽取类处理
3. 设计享元工厂类,采用对象池管理享元对象。
一般使用场景是对象池,将对象缓存。极大减少内存中对象的数量相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步