设计模式:享元模式
享元模式中的享指的共享的意思,该模式以共享的方式支持某些对象的重用(特别是一些大的对象)以此节约空间。典型的是以时间换空间的做法。
例如:java语言中String类型就是使用享元模式。对于JVM来说,String对象都是共享的。如果一个系统中两个String对象所包含的字符串内容相同,jvm
实际上只创建一个String对象提供两个引用。
享元模式一般的角色:
享元工厂类(FlyWeight享元工厂类):管理享元对象
抽象享元类(FlyWeight抽象类):接口或抽象类,向外界提供对象内部状态。
具体享元类(ConcreteFlyWeight):继承自抽象享元类。为内部状态提供成员变量存储。
非共享享元类(UnshareConcreteFlyWeight):不能被共享的一些子类。
享元对象能作为共享的的关键是区分内部状态和外部状态。
内部状态:可以共享。
外部状态:不可以共享。
例子:
描述一个围棋软件,每个棋子是一个对象(颜色,形状等)这些是可以共享的,对应内部状态。只有棋子的位置不是共享的,对应外部状态。
/** * 享元类 */ public interface ChessFlyWeight { //颜色 void setColor(String c); String getColor(); //描述位置 void display(Position c); }
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; } }
外部状态位置单独设计一个类
/** * 外部状态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; } }
享元工厂类
/** * 享元工厂类 * 创建和管理享元对象 */ 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; } } }
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. 设计享元工厂类,采用对象池管理享元对象。
一般使用场景是对象池,将对象缓存。极大减少内存中对象的数量相同或相似对象内存中只存一份,极大的节约资源,提高系统性能