设计模式笔记之十一 (享元模式)
享元模式
享元模式的英文说法是:Flyweight Parrern, 又被译作蝇量模式。这两种译法分别说明了其需要解决的问题,解决问题的方式:
当我们需要解决许多轻量类引起的资源开销问题的时候(蝇量模式),我们可以用重用共同点的元素(享元模式)的方法来解决。
正如我们实验室最近接到的一个订单的最终解决方案一样。
前段时间我们的太阳市场部得到一笔大订单:太阳国某富豪要举办一场盛大的聚会,他们需要订购一批女人来满足他的客人们:
class NvRen { private String name; private String head; private String body; private String type; public NvRen(String name, String head, String body, String type) { this.name = name; this.head = head; this.body = body; this.type = type; } public void service() { System.out.println("服务者:" + this.name); } } public class FlyWeight { public static void main(String[] args) { int customerNumber = 1000; String customer = "客人"; for (int i = 0; i < customerNumber; i++) { String customerName = customer + i; System.out.print("客人: " + customerName + " 的"); new NvRen("松岛" + i + "子", "瓜子脸", "葫芦型", "气质高雅型").service(); } } }
但是当我们准备生产的时候,有个对太阳国比较有研究的技术宅说,据他的了解,在太阳国就算再富有的富豪也找不出一套房子来容纳1000个客人,如果再加上我们的1000个女人产品,肯定连站的地方都没有,更别说躺下或者趴下了。
我们一想也是,到时候那个富豪别一看放不下这么多的人而不定我们的产品了,那就比较尴尬了。
于是我们想到既然没有那么多的地方来容纳那么多的"女人",我们可以少生产一点,反正也没有同时提供service的地方。于是一个新的解决方案出炉了,就是我们提供一个小黑屋,里面只有一个"女人",但是服务不同客户的时候报不同的名字:
class NvRen { private String name; private String head; private String body; private String type; public NvRen(String name, String head, String body, String type) { this.name = name; this.head = head; this.body = body; this.type = type; } public void service(String name) { System.out.println("服务者:" + name); } } class BlackRoom { // 单例的小黑屋 private static BlackRoom br; private static final Object o = new Object(); private static NvRen nr; private BlackRoom() { nr = new NvRen("", "瓜子脸", "葫芦型", "气质高雅型"); // 小黑屋里面只有一个女人的实例 } public static BlackRoom getInstance() { if (br == null) { synchronized (o) { if (br == null) { br = new BlackRoom(); } } } return br; } public void service(int i) { String name = "松岛" + i + "子"; nr.service(name);// 小黑屋里面的女人在提供service的时候报不同的名字 } } public class FlyWeight { public static void main(String[] args) { int customerNumber = 1000; String customer = "客人"; for (int i = 0; i < customerNumber; i++) { String customerName = customer + i; System.out.print("客人: " + customerName + " 的"); BlackRoom.getInstance().service(i); } } }
现在我们只要造一个"女人"就能满足富豪的需求了,而且不会因为地方不够而担心了。
当然,最终我们提供给客户的时候当然不是这么简单的单个产品,我们会提供好几种不同的女人来满足不同客人的需求:
import java.util.HashMap; class NvRen { private String name; private String head; private String body; private String type; public NvRen(String name, String head, String body, String type) { this.name = name; this.head = head; this.body = body; this.type = type; } public void service(String name) { System.out.println("服务者:" + name + "(真实的女人编码:" + this.hashCode() + ")"); } } class BlackRoom { // 单例的小黑屋 private static BlackRoom br; private static final Object o = new Object(); private static HashMap<String, NvRen> nrs = new HashMap<String, NvRen>(); private BlackRoom() { // 供客人使用的几种类型 nrs.put("类型1", new NvRen("", "瓜子脸", "葫芦型", "气质高雅型")); nrs.put("类型2", new NvRen("", "圆脸", "葫芦型", "邻家少女型")); nrs.put("类型3", new NvRen("", "圆脸脸", "纤细型", "萝莉型")); nrs.put("类型4", new NvRen("", "瓜子脸", "葫芦型", "御姐型")); // 专供主人使用的女主人 nrs.put("女主人", new NvRen("", "面饼脸", "纺锤型", "屠夫型"));// 女主人是不共享的 } public static BlackRoom getInstance() { if (br == null) { synchronized (o) { if (br == null) { br = new BlackRoom(); } } } return br; } public void service(Integer i) { String name = ""; String type = ""; if (i != null) { name = "松岛" + i + "子"; type = "类型" + (Math.round(Math.random() * 3) + 1); } else { name = "女主人"; type = "女主人"; } nrs.get(type).service(name); // 小黑屋里面的女人在提供service的时候报不同的名字 } } public class FlyWeight { public static void main(String[] args) { // 1000个客人 int customerNumber = 1000; String customer = "客人"; for (int i = 0; i < customerNumber; i++) { String customerName = customer + i; System.out.print(customerName + "的"); BlackRoom.getInstance().service(i); } System.out.print("主人的"); // 主人 BlackRoom.getInstance().service(null); } }
以上就是一个享元模式的应用。当然由于这个模式应用的非常少(本人还没有在项目中用到过),所以如有不当的地方请斧正。