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.总结
通过享元对象的内部状态来判断此对象是否需要创建,将“对象是否相同”细化到属性上。优势很明显,但需将部分状态(属性)外部化,也增加了系统的复杂性,还得确保与内部状态互不影响。
登录 | 立即注册