以共享的方式高效地支持大量细粒度的对象
享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)
- 内部状态:存储在享元对象内部的、可以共享的信息,不会随环境改变而改变
- 外部状态:随环境改变而改变的不可共享状态。必须由客户端保存,并在享元对象创建后,在需要使用的时候再传入享元对象内部
作用
降低大量重复的、细粒度的类在内存中的开销
四个角色
-
抽象享元角色(Flyweight)
- 对享元类进行抽象
- 可以通过参数将外部状态传入
/** * 抽象享元角色(Flyweight) * 棋子 * * @author Jenson */ public interface Chesspiece { /** * 落子 * * @param x 横轴 * @param y 纵轴 */ void put(int x, int y); }
-
具体享元角色(ConcreteFlyweight)
- 实现抽象享云定义的业务
- 内部状态与环境无关,才能使享云对象在系统内共享
/** * 具体享元角色 * <p> * 棋子实现 * * @author Jenson */ public class ChesspieceFlyweight implements Chesspiece { /** * 棋子颜色,享元角色的内部状态 * 存储在享元对象内部的、可以共享的信息,不会随环境改变而改变 */ private String color; public ChesspieceFlyweight(String color) { this.color = color; } @Override public void put(int x, int y) { System.out.println("在("+x+","+y+")的位置放置了一个"+color+"子"); } }
-
享元工厂角色(FlyweightFactory)
- 构造一个池容器,负责创建和管理享云角色,并提供从池容器中获得对象的方法
- 当客户端请求享元对象时,先检查系统中是否已经有符合要求的享元对象,如果有,则提供这一个,没有则创建一个合适的享 元对象
/** * 享元工厂角色(FlyweightFactory) * <p> * 负责创建和管理棋子 * * @author Jenson */ public class ChesspieceFactory { /** * 使用常量:享元角色的内部状态无法更改 */ static final Chesspiece WHITE_CHESSPIECE = new ChesspieceFlyweight("白"); static final Chesspiece BLACK_CHESSPIECE = new ChesspieceFlyweight("黑"); /** * 提供从池容器中获得对象的方法 * <p> * 个人觉得这里的实现方式可以参考"懒汉式单例模式"的实现方式, * 以实现"当客户端请求享元对象时,先检查系统中是否已经有符合要求的享元对象, * 如果有,则提供这一个,没有则创建一个合适的享元对象"的要求 * * @param color 颜色 * @return 棋子对象 */ public static Chesspiece getChesspiece(String color) { if (color.equals("白")) { return WHITE_CHESSPIECE; } else if (color.equals("黑")) { return BLACK_CHESSPIECE; } else { return null; } } }
/** * 享元工厂角色(FlyweightFactory) * <p> * 负责创建和管理棋子 * * @author Jenson */ public class ChesspieceFactory2 { private static Map<String, Chesspiece> pool = new HashMap(); private ChesspieceFactory2() { } /** * 提供从池容器中获得对象的方法 * * @return 棋子 */ public static Chesspiece getChesspiece(String color) { Chesspiece chesspiece = pool.get(color); if (chesspiece == null) { chesspiece = new ChesspieceFlyweight(color); pool.put(color, chesspiece); } return chesspiece; } }
-
客户端角色(Client)
- 需要自行存储享元对象的外部状态
调用
/**
* @author Jenson
*/
public class FlyweightMain {
public static void main(String[] args) {
// 对象从享元工厂中获取
Chesspiece cp1 = ChesspieceFactory.getChesspiece("白");
assert cp1 != null;
cp1.put(2,3);
Chesspiece cp2 = ChesspieceFactory.getChesspiece("黑");
assert cp2 != null;
cp2.put(4,5);
System.out.println("------------------------------------------");
// 对象从享元工厂中获取
Chesspiece p1 = ChesspieceFactory2.getChesspiece("黄");
p1.put(7,8);
Chesspiece p2 = ChesspieceFactory2.getChesspiece("红");
p2.put(0,1);
}
}