享元模式以共享的方式高效地支持大量的细粒度对象。
享元对象能做到共享的关键是区分内蕴状态和外蕴状态。
一个内蕴状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的,因此,一个享元可以具有内蕴含状态并可以共享。
一个外蕴状态是随环境改变而改变的,不可以共享的状态,享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。
享元模式的种类:单纯享元模式和复合享元模式两种形式
1,享元模式
在单纯享元模式中,所有的享元对象都是可以共享的
抽象享元角色:此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口,那些需要外蕴状态的操作可以通过调用商业方法以参数形式传入
具体享元角色:实现抽象享元角色所规定的接口,如果有内蕴状态的话,必须负责为内蕴状态提供存储空间,享元对象的内蕴状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享
享元工厂角色:本角色负责创建和管理享元角色,本角色必须保证享元对象可以被系统适当地共享,当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个复合要求的享元对象,如果有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。
客户端角色:本角色需要维护一个对所有享元对象的引用,本角色需要自行存储所有享元对象的外蕴状态。
1. public interface Flyweight {
2. public void operation(String state);
3. }
1. public class ConcerteFlyweight implements Flyweight{
2. //内蕴状态
3. private Character intrinsicState = null;
4. //传进来的参数属于外晕状态
5. public ConcerteFlyweight(Character state) {
6. this.intrinsicState = state;
7. }
8.
9. public void operation(String state) {
10. System.out.println("intrinsicState="+intrinsicState+",Extrinsic State="+state);
11. }
12.
13. }
1. public class FlyweightFactory {
2.
3. private HashMap flies = new HashMap();
4.
5. private Flyweight fly;
6.
7. public FlyweightFactory(){
8.
9. }
10.
11. //字体样式
12. public Flyweight factory(Character state){
13. if(flies.containsKey(state)){
14. return (Flyweight)flies.get(state);
15. }else{
16. fly = new ConcerteFlyweight(state);
17. flies.put(state, fly);
18. return fly;
19. }
20. }
21. }
22. public class Client {
23.
24. public static void main(String[] args){
25. FlyweightFactory factory=new FlyweightFactory();
26. Flyweight fly=factory.factory(new Character('a'));
27. fly.operation("罗马字符");
28. fly.operation("新罗马字符");
29. fly=factory.factory(new Character('b'));
30. fly.operation("阿拉伯字符");
31. }
32. }
2,复合享元模式
单纯享元模式中,所有的享元对象都是单纯享元对象,也就是说都是可以直接共享的。如果将一些单纯享元使用合成模式加以复合,形成复合享元对象,这样的复合享元对象本身不能共享,但是他们可以分解成单纯享元对象,然后可以共享。
1. public interface Flyweight {
2. public void operation(String state);
3. }
4.
5.
6. public class ConcreteFlyweight implements Flyweight
7. {
8. private Character intrinsicState=null;
9. //构造子,内蕴状态作为参数传入
10. public ConcreteFlyweight(Character state)
11. {
12. this.intrinsicState=state;
13. }
14. //外蕴状态作为参数传入方法
15. public void operation(String state)
16. {
17. System.out.println("Intrinsic state="+intrinsicState+",Extrinsic State="+state);
18. }
19. }
20. public class ConcreteCompositeFlyweight implements Flyweight{
21.
22. private HashMap flies=new HashMap(10);
23. private Flyweight flyweight;
24. public ConcreteCompositeFlyweight() { }
25. //增加一个新的单纯享元对象到聚集中
26. public void add(Character key,Flyweight fly)
27. {
28. flies.put(key,fly);
29. }
30. //外蕴状态作为参数传入到方法中
31. public void operation(String extrinsicState)
32. {
33. Flyweight fly=null;
34. for(Iterator it=flies.entrySet().iterator();it.hasNext();)
35. {
36. Map.Entry e=(Map.Entry)it.next();
37. fly=(Flyweight)e.getValue();
38. fly.operation(extrinsicState);
39. }
40. }
41. }
42. public class FlyweightFactory
43. {
44. private HashMap flies=new HashMap();
45.
46. public FlyweightFactory() { }
47.
48. //单纯享元工厂方法,所需状态以参量形式传入
49. public Flyweight factory(Character state)
50. {
51. if(flies.containsKey(state))
52. {
53. return (Flyweight)flies.get(state);
54. } else {
55. Flyweight fly=new ConcreteFlyweight(state);
56. flies.put(state,fly);
57. return fly;
58. }
59. }
60.
61. //符合享元工厂方法,所需状态以参量形式传入,这个参量巧好可以使用string类型
62. public Flyweight factory(String compositeState)
63. {
64. ConcreteCompositeFlyweight compositeFly=new ConcreteCompositeFlyweight();
65. int length=compositeState.length();
66. Character state=null;
67. for(int i=0;i<length;i++)
68. {
69. state=new Character(compositeState.charAt(i));
70. System.out.println("factory("+state+")");
71. compositeFly.add(state,this.factory(state));
72. }
73. return compositeFly;
74. }
75.
76. }
77. public class Client {
78.
79. /**
80. * @param args
81. */
82. public static void main(String[] args) {
83.
84. FlyweightFactory factory=new FlyweightFactory();
85. Flyweight fly=(Flyweight) factory.factory("abac");
86. fly.operation("罗马字符");
87. }
88.
89. }
测试结果:
factory(a) factory(b) factory(a) factory(c) Intrinsic state=a,Extrinsic State=罗马字符 Intrinsic state=c,Extrinsic State=罗马字符 Intrinsic state=b,Extrinsic State=罗马字符
这就说明了,将复合享元对象差分为若干个单纯享元对象处理,并且外蕴是相同的。