设计模式笔记之十一 (享元模式)

享元模式

享元模式的英文说法是: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);
    }
}

以上就是一个享元模式的应用。当然由于这个模式应用的非常少(本人还没有在项目中用到过),所以如有不当的地方请斧正。

posted @ 2013-05-21 15:29  biglaojiang  阅读(1046)  评论(3编辑  收藏  举报