设计模式——结构型模式(六)

Flyweight(享元模式)

目标

使用共享技术有效地支持大量细粒度的对象。

结构

结构图

享元接口由享元工厂生产出来,其中包含着可被共享的享元与不可共享的享元。当用户需要一个享元对象的时候,享元工厂将根据情况生产或者返回对象。

协作

时序图

用户通过调用享元工厂以得到相应的享元对象,这个对象将会根据是否是一个可被共享的享元对象让工厂对其能不能作为一个享元来进行相应的操作。

适用情形

  1. 一个程序使用了大量的造成了极大的存储开销的对象;

  2. 这些对象的大部分属性可以变为外部状态,并且这些外部状态可以被对象中剥离下来;

  3. 程序不依赖于对象标志,使用相同的对象对程序并不会造成任何的误解或者冲突等。

参与者

  • Flyweight

    一个可以接受外部状态的接口,作为享元的基类。

  • ConcreteFlyweight

    实现Flyweight接口,并且存储了独立于ConcreteFlyweight对象所在场景内部状态,并且必须是一个可共享的对象。

  • UnsharedConcreteFlyweight

    一个不会被共享的享元对象,通常作为Flyweight层次结构中,ConcreteFlyweight对象的父节点。(例如一个文字编辑文件中Row和Column)

  • FlyweightFactory

    创建并且管理Flyweight对象,确保能够正确地使用共享一个享元对象。

  • Client

    维持一个Flyweight的引用指针,计算、存储所有Flyweight对象的外部状态。

效果

  1. 使用享元模式的时候,将会在计算、传输、查找外部状态时会产生很多运行时的额外开销,这些额外开销将会通过减少的对象存储空间使用所抵消。

  2. 存储节约的主要因素:

    • 因为共享、示例总数减少的数目;

    • 对象内部状态的平均数目;

    • 外部共享状态是计算出来还是存储下来的。

  3. 外部状态理想条件下应该是可以通过某种对象结构直接计算出来的,并且要求的存储量非常小。

  4. 享元模式将会通过单例模式以及工厂模式进行管理,可以使用对象表进行管理。

代码示例

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
class Printer {
private HashMap<Character, MovableType> typeMap;
public Printer() {
this.typeMap = new HashMap<Character, MovableType>();
}
public MovableType getType(Character c) {
if(!typeMap.keySet().contains(c)) {
typeMap.put(c, MovableType.instance(c));
}
return typeMap.get(c);
}
}
abstract class MovableType {
private static Class[] classList;
protected MovableType();
public static MovableType instance(char c) {
if (classList == null) {
classList = new Class[26];
classList[1] = TypeA.class;
classList[2] = TypeB.class;
}
return new classList[c - 'A'].newInstance();
}
abstract public void print();
}
class TypeA extends MovableType {
@Override
public void print() {
System.out.println("A");
}
}
class TypeB extends MovableType {
@Override
public void print() {
System.out.println("B");
}
}
public class Client {
private MovableType movableType;
private String color;
private String size;
private Printer printer;
public Client() {
this.printer = new Printer();
}
public void addColor(String color) {
this.color = color;
}
public void addSize(String size) {
this.size = size;
}
public void use() {
System.out.println(color + " " + size);
movableType.print();
}
public static void main(String args[]) {
Clinet client = new Client();
client.movableType = client.printer.getType('A');
client.addColor("red");
client.addSize("Large");
client.use();
}
}

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2018 Alex's Blog All Rights Reserved.

Yifeng Tang hält Urheberrechtsansprüche.