享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
何时使用: 1、系统中有大量对象。 2、这些对象消耗大量内存。 3、这些对象的状态大部分可以外部化。 4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。 5、系统不依赖于这些对象身份,这些对象是不可分辨的。
如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用 HashMap 存储这些对象。
应用实例: 1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。
优点:大大减少对象的创建,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。
注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。
假设有个销售单模板的需求,每个销售人对应自己的模板不变。
销售单接口
1 /** 2 * 销售单接口 3 * @author ko 4 */ 5 public interface SalesSlip { 6 void print(); 7 }
设备销售单
1 import java.math.BigDecimal; 2 import java.util.Date; 3 4 public class DeviceSalesSlip implements SalesSlip { 5 6 public String salesPerson; 7 8 public String title; 9 public String address; 10 public Date date; 11 public BigDecimal salesVolume; 12 13 public DeviceSalesSlip(String salesPerson) { 14 this.salesPerson = salesPerson; 15 } 16 17 @Override 18 public void print() { 19 System.out.println("DeviceSalesSlip [salesPerson=" + salesPerson + ", title=" + title + ", address=" + address + ", date=" 20 + date + ", salesVolume=" + salesVolume + "]"); 21 } 22 23 24 public void setTitle(String title) { 25 this.title = title; 26 } 27 28 29 public void setAddress(String address) { 30 this.address = address; 31 } 32 33 34 public void setDate(Date date) { 35 this.date = date; 36 } 37 38 39 public void setSalesVolume(BigDecimal salesVolume) { 40 this.salesVolume = salesVolume; 41 } 42 43 }
生成销售单的工厂类
1 import java.util.HashMap; 2 3 public class SalesSlipFactory { 4 5 private static final HashMap<String, SalesSlip> ssMap = new HashMap<>(); 6 7 public static SalesSlip getSalesSlip(String salesPerson){ 8 DeviceSalesSlip deviceSalesSlip = (DeviceSalesSlip) ssMap.get(salesPerson); 9 if (deviceSalesSlip == null) { 10 deviceSalesSlip = new DeviceSalesSlip(salesPerson); 11 ssMap.put(salesPerson, deviceSalesSlip); 12 System.out.println("create deviceSalesSlip by person:"+salesPerson); 13 } 14 return deviceSalesSlip; 15 } 16 }
测试类
1 public class Test { 2 3 private static final String[] salesPersons = new String[]{"djii","iioi","tgyg","ssaw","qqww","nnjk"}; 4 5 public static void main(String[] args) { 6 for (int i = 0; i < 6; i++) { 7 DeviceSalesSlip deviceSalesSlip = (DeviceSalesSlip) SalesSlipFactory.getSalesSlip(salesPersons[i]); 8 deviceSalesSlip.setTitle("test title "+i); 9 deviceSalesSlip.setDate(new Date()); 10 deviceSalesSlip.setAddress("test address "+i); 11 deviceSalesSlip.setSalesVolume(new BigDecimal(new Random().nextInt(10))); 12 deviceSalesSlip.print(); 13 } 14 15 } 16 }
运行结果
create deviceSalesSlip by person:djii DeviceSalesSlip [salesPerson=djii, title=test title 0, address=test address 0, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=9] create deviceSalesSlip by person:iioi DeviceSalesSlip [salesPerson=iioi, title=test title 1, address=test address 1, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=9] create deviceSalesSlip by person:tgyg DeviceSalesSlip [salesPerson=tgyg, title=test title 2, address=test address 2, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=7] create deviceSalesSlip by person:ssaw DeviceSalesSlip [salesPerson=ssaw, title=test title 3, address=test address 3, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=2] create deviceSalesSlip by person:qqww DeviceSalesSlip [salesPerson=qqww, title=test title 4, address=test address 4, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=6] create deviceSalesSlip by person:nnjk DeviceSalesSlip [salesPerson=nnjk, title=test title 5, address=test address 5, date=Tue Jul 11 13:40:40 CST 2017, salesVolume=8]