Flyweight Pattern 对象结构型模式
意图
运用共享技术有效地支持大量细粒度的对象
结构
其中:
-
Flyweight 描述一个接口,通过这个接口 Flyweight 可以接受并作用于外部状态
-
ConcreteFlyweight 实现 Flyweight 接口,并为内部状态 (如果有) 增加存储空间。ConcreteFlyweight 对象必项是可共享的。它所存储的状态必须是内部的,即它必须独立于 ConcreteFlyweight 对象的场景
-
并非所有的 Flyweight 子类都需要被共享。Flyweight 接口使共享成为可能,但它并不强制共亨。在 Flyweight 对象结构的某些层次,UnsharedConcreteFlyweight 对象通常将 ConcreteFlyweight 对象作为子结点
-
FlyweightFactory 创建并管理 Flyweight 对象;确保合理地共享 Flyweight,当用户请求一个 Flyweight 时,FlyweightFactory 对象提供一个已创建的实例或者不存在时创建一个实例
-
Client 维持一个对 Flyweight 的引用;计算或存储一个或多个 Flyweight 的外部状态
适用性
Flyweight 模式适用于:
- 一个应用程序使用了大量的对象
- 完全由于使用大量的对象,造成很大的存储开销
- 对象的大多数状态都可变为外部状态
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
- 应用程序不依赖于对象标识。由于 Flyweight 对象可以被共享,所以对于概念上明显有别的对象,标识测试将返回真值
例子 1
现要开发一个网络围棋程序,允许多个玩家联机下棋。由于只有一台服务器,为节省内存空间,采用享元模式实现该程序,类图如下
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import java.util.ArrayList;
enum PieceColor {BLACK, WHITE} // 棋子颜色
class PiecePods{ // 棋子位置
private int x;
private int y;
public PiecePods(int a, int b){
x = a;
y = b;
}
public int getX(){
return x;
}
public int getY() {
return y;
}
}
abstract class Piece{ // 棋子定义
protected PieceColor m_color; // 颜色
protected PiecePods m_pos; // 位置
public Piece(PieceColor color, PiecePods pos){
this.m_color = color;
this.m_pos = pos;
}
public abstract void draw();
}
class BlackPiece extends Piece{
public BlackPiece(PieceColor color, PiecePods pos){
super(color, pos);
}
@Override
public void draw(){
System.out.println("Draw a black piece");
}
}
class WhitePiece extends Piece{
public WhitePiece(PieceColor color, PiecePods pos){
super(color, pos);
}
@Override
public void draw(){
System.out.println("Draw a white piece");
}
}
class PieceBoard{ // 棋盘上已有的棋子
private static final ArrayList<Piece> m_arrayPiece = new ArrayList<>();
private String m_blackName; // 黑方名称
private String m_whiteName; // 白方名称
public PieceBoard(String black, String white){
m_blackName = black;
m_whiteName = white;
}
// 一步棋,在棋盘上放一颗棋子
public void setPiece(PieceColor color, PiecePods pos){
Piece piece = null;
if(color == PieceColor.BLACK){ // 放黑子
piece = new BlackPiece(color, pos);
System.out.println(m_blackName + pos.getX() + pos.getY());
piece.draw();
}else{ // 放白子
piece = new WhitePiece(color, pos);
System.out.println(m_whiteName + pos.getX() + pos.getY());
piece.draw();
}
m_arrayPiece.add(piece);
}
}
例子 2
五子棋
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class FlyWeightPattern {
public static void main(String[] args) {
PieceFactory factory = new PieceFactory();
Piece wp1 = factory.getPiece(0);
wp1.draw(2023, 0527);
}
}
class PieceFactory{
private Piece[] pieces = {new WhitePiece(), new BlackPiece()};
public Piece getPiece(int key){
if(key == 0) return pieces[0];
else return pieces[1];
}
}
abstract class Piece{
protected String color;
public abstract void draw(int x, int y);
}
class WhitePiece extends Piece{
public WhitePiece(){
this.color = "white";
}
@Override
public void draw(int x, int y){
System.out.println("draw a " + this.color + " piece x: " + x + " y: " + y);
}
}
class BlackPiece extends Piece{
public BlackPiece(){
this.color = "Black";
}
@Override
public void draw(int x, int y){
System.out.println("draw a " + this.color + " piece x: " + x + " y: " + y);
}
}
例子 3
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class FlyWeightPattern {
public static void main(String[] args) {
ShapeFactory sf = new ShapeFactory();
Random r = new Random();
String[] colors = {"red", "blue", "green", "white", "black"};
for (int i = 0; i < 10; i++) {
int x = r.nextInt(colors.length);
Shape s = sf.getShape(colors[x]);
s.draw(r.nextInt(2023), r.nextInt(527));
}
}
}
class ShapeFactory{
private Map<String, Shape> map = new HashMap<>();
public Shape getShape(String key){
if (!map.containsKey(key)) {
map.put(key, new Circle(key));
System.out.println("create new circle, color: " + key);
}
return map.get(key);
}
}
abstract class Shape{
protected String color;
public abstract void draw(int x, int y);
}
class Circle extends Shape{
public Circle(String color){
this.color = color;
}
@Override
public void draw(int x, int y) {
System.out.println("draw a " + this.color + " circle x: " + x + " y: " + y);
}
}