JobPlus知识库 IT 软件开发 文章
享元模式——七种结构型模式之一

1.前言

通过一个全局变量来避免重复创建对象而产生的消耗,若系统存在大量的相似对象时,又该如何处理?参照单例模式,可通过对象池缓存可共享的对象,避免创建多对象,尽可能减少内存的使用,提升性能,防止内存溢出。

2.概念

享元模式使用共享对象可有效地支持大量细粒度的对象。为了解释一下,何为细粒度对象,引用《Android源码设计模式解析与实战》中的描述。

对象中的部分状态是可以共享的,这些状态称为内部状态,它们不会随着环境变化;相反,不可共享的状态称为外部状态,它们会随着环境的改变而改变。

由于共享的不是一个对象,所以需要容器,最经典的便是Map。它的键是内部状态,值为对象本身。获取对象的过程:先判断容器中是否有缓存,若有,直接使用;若没有,创建对象并存入容器。

3.场景

一家网络会所想订购一批电脑,为了满足不同档次的用户需求,要多种配置和款式:

  • 会员与普通用户使用的电脑配置基本相似,仅内存更大;
  • 超级会员则从机箱开始完全不同。

老板便联系电脑销售点,希望服务人员带几款样机过来体验。服务人员详细询问老板的需求后,带了两个配置好的机箱,几张内存条就过来了。

4.写法// 定义所有对象具有的行为 public interface Mainboard {    void showConfig(); }// 被创建的具体对象 public class Computer implements Mainboard {    private String memery;    private String computerCase;    private String cpu;    public Computer(String memery, String computerCase, String cpu) {        this.memery = memery;        this.computerCase = computerCase;        this.cpu = cpu;    }    public void setMemery(String memery) {        this.memery = memery;    }    public void setCpu(String cpu) {        this.cpu = cpu;    }    @Override    public void showConfig() {        System.out.println("电脑的配置是: " + computerCase + " / " + cpu + " / " + memery);    } }

若展示会员机,则只需要更换内存即可;若展示超级会员机,只能使用另一个机箱。

// 享元工厂,管理对象池和创建对象 public class Service {    static Map<String, Mainboard> computerMap = new ConcurrentHashMap<>();    public static void getInfo(String memery, String computerCase, String cpu) {        if (computerMap.containsKey(computerCase)) {            System.out.println("使用缓存->");            Mainboard mainboard = computerMap.get(computerCase);            if (mainboard instanceof Computer) {                Computer computer = (Computer) mainboard;                computer.setMemery(memery);                computer.setCpu(cpu);                computer.showConfig();            }        } else {            System.out.println("创建对象->");            Mainboard mainboard = new Computer(memery, computerCase, cpu);            computerMap.put(computerCase, mainboard);            mainboard.showConfig();        }    } }public class Client {    public static void main(String[] args) {        // 开始向会所老板展示        Service.getInfo("8G", "技嘉", "i5");        Service.getInfo("16G", "技嘉", "i5");        Service.getInfo("16G", "华硕", "i7");    } }

Java中的String是存在常量池中的,逻辑与这个类似。当其它地方使用相同字符串时,则直接使用缓存中的,不会重复创建。这种只适合字面值赋值,即直接通过双引号设置的字符串值;若是通过new构建,则是新的对象。

5.总结

通过享元对象的内部状态来判断此对象是否需要创建,将“对象是否相同”细化到属性上。优势很明显,但需将部分状态(属性)外部化,也增加了系统的复杂性,还得确保与内部状态互不影响。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏支持
213人赞 举报
分享到
用户评价(0)

暂无评价,你也可以发布评价哦:)

扫码APP

扫描使用APP

扫码使用

扫描使用小程序