(使用共享对象可有效地支持大量的细粒度的对象。)
假设开发一个围棋程序,围棋程序的围棋的棋子包含了颜色、大小、位置等信息。在定义一个棋盘容器来存放这些棋子。 我们可以发现,棋盘的成员变量包含了一个棋子所有的属性,我们需要为每一个颜色大小开辟内存来储存这些信息,而一盘棋需要上百个棋子,这种实现方法占得空间太大了。
我们可以发现棋子的颜色形状等信息都是相同的,我们称这些是可以共享的属于内在的属性,还有位置信息无法共享称为外在属性
因此,可以这样设计,只需定义两颗棋子对象,一颗黑棋与一颗白棋,者两个对象包含棋子得到内在属性。再将外在属性(位置)提取出来放在单独的容器中。
这就是享元模式。
享元模式中通常会出现工厂模式,需要创建一个享元工厂来负责维护一个享元池,用来存储具有相同内部状态的享元对象。
单纯享元结构: 所有的享元对象都是可以共享的。
复合享元模式:将一些单纯享元使用合成模式加以复合,形成复合享元对象。这样的复合享元对象本身不能共享,但是他们可以分解成单纯享元对象,而后者则可以共享。
抽象享元类:
1 public abstract class Flyweight { 2 private String shape = null; 3 private String color = null; 4 private int size = 0; 5 6 public Flyweight(String shape, String color, int size) { 7 super(); 8 this.shape = shape; 9 this.color = color; 10 this.size = size; 11 } 12 13 public String getShape() { 14 return shape; 15 } 16 17 public String getColor() { 18 return color; 19 } 20 21 public void setColor(String color) { 22 this.color = color; 23 } 24 25 public void setShape(String shape) { 26 this.shape = shape; 27 } 28 29 public int getSize() { 30 return size; 31 } 32 33 public void setSize(int size) { 34 this.size = size; 35 } 36 37 public abstract void show(String externstate); 38 }
具体享元类:
1 public class ConcreteFlyweight extends Flyweight{ 2 3 4 public ConcreteFlyweight(String shape, String color, int size) { 5 super(shape, color, size); 6 7 } 8 9 @Override 10 public void show(String externstate) { 11 System.out.println("color:"+getColor()); 12 // System.out.println(" shape:"+getShape()+" size:"+getSize()); 13 System.out.println(" 外部状态: "+externstate); 14 } 15 16 }
享元工厂类:
1 import java.util.HashMap; 2 import java.util.Map; 3 4 public class FlyweightFactory { 5 private static FlyweightFactory flyweightFactory = new FlyweightFactory(); 6 private static final String white = "white"; 7 private static final String black = "black"; 8 private static Map<String,Flyweight> map = new HashMap<String, Flyweight>(); 9 private FlyweightFactory() { 10 System.out.println("构造方法被调用!"); 11 } 12 static public FlyweightFactory getInstance() { 13 return flyweightFactory; 14 } 15 static public Flyweight getFlyweight(String key) { 16 if (map.get(key)!=null) { 17 return map.get(key); 18 } 19 else if (key.equals(white)) { 20 //不可将初始化棋子放入构造器 会造成指针混乱 21 map.put(white,new ConcreteFlyweight("圆", "white", 5)); 22 return map.get(key); 23 }else if (key.equals(black)) { 24 map.put(black,new ConcreteFlyweight("圆", "black", 5)); 25 return map.get(key); 26 }{ 27 System.out.println("无此享元对象"); 28 return null; 29 } 30 31 32 33 } 34 }
用户测试类:
1 public class FlyweightPattern { 2 3 public static void main(String[] args) { 4 5 FlyweightFactory flyweightFactory = FlyweightFactory.getInstance(); 6 //可以将此对象的引用传入容器再在容器内添加位置信息,容器内只是引用有多份,而占内存的棋子只有一个黒子一个白子 7 Flyweight f1 = flyweightFactory.getFlyweight("white"); 8 f1.show("x = 1,y = 2");// 9 Flyweight f2 = flyweightFactory.getFlyweight("black"); 10 f2.show("x = 2,y = 3"); 11 } 12 13 }