设计模式享元模式解决重复对象的内存浪费问题
一、定义
"享元"指被共享的单元。享元模式就是通过复用对象,以达到节省内存的目的。
尝试复用现有的同类对象,如果未找到匹配的对象,则创建新对象。
意图:运用共享技术有效地支持大量细粒度的对象。
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。 二、内部状态和外部状态
享元模式提出了两个要求: 细粒度和共享对象。这里涉及到内部状态和外部状态,即将对象的信息分为两个部分:内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态
以围棋为例,围棋只有黑白二色,其颜色不会随环境改变而改变,所以围棋颜色就是围棋的内部状态,可共享;棋子之间的差别在于位置不同,而落子后,棋子的位置会发生变化,所以棋子的坐标是棋子的外部状态,不可共享。 三、享元模式原理类图
(1)抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
(2)具体享元角色(Concrete Flyweight):实现抽象享元角色中所规定的接口。
(3)非享元角色(Unsharable Flyweight) :是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
(4)享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。四、案例
以网站项目展示为例,有的要求以新闻形式发布,有的要求以博客形式发布,有的要求以 微信公众号形式发布。
整合到一个网站中,共享其相关的代码和数据,对于硬盘、内存、CPU、数据库空间等服务器资源都可以达成共享,减少服务器资源。
//抽象享元角色 public abstract class WebSite { public abstract void use(User user); } //具体享元角色 public class ConcreteWebSite extends WebSite { private String type = "";//网站发布形式,内部状态,共享部分 public ConcreteWebSite(String type) { this.type = type; } @Override public void use(User user) { System.out.println("网站的发布形式为:"+type+","+user.getName()+"在使用"); } } //非享元角色 public class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } //享元工厂 public class WebSiteFactory { //集合,充当池的作用 private HashMap pool = new HashMap<>(); //根据网站类型,返回一个网站,如果没有就创建一个并放入池中 public WebSite getWebSiteCategory(String type){ if(!pool.containsKey(type)){ pool.put(type,new ConcreteWebSite(type)); } return pool.get(type); } //获取网站分类数 public int getWebSiteCount(){ return pool.size(); } } //客户端 public class Client { public static void main(String[] args) { //创建一个工程类 WebSiteFactory webSiteFactory = new WebSiteFactory(); //A以一个新闻形式发布网站 WebSite newsWebsite = webSiteFactory.getWebSiteCategory("新闻"); newsWebsite.use(new User("A")); //B以一个博客形式发布网站 WebSite blogWebsite1 = webSiteFactory.getWebSiteCategory("博客"); blogWebsite1.use(new User("B")); //C以一个博客形式发布网站 WebSite blogWebsite2 = webSiteFactory.getWebSiteCategory("博客"); blogWebsite2.use(new User("C")); //D以一个博客形式发布网站 WebSite blogWebsite3 = webSiteFactory.getWebSiteCategory("博客"); blogWebsite3.use(new User("D")); //实际网站发布分类实例 System.out.println("实际网站发布分类实例:"+webSiteFactory.getWebSiteCount()); } } 五、应用
在Java Integer的实现中,-128到127之间的整型对象会被事先创建好,缓存在IntegerCache类中。当我们使用自动装箱或者valueOf()来创建这个数值区间的整型对象时,会复用IntegerCache类事先创建好的对象。这里的IntegerCache类就是享元工厂类,事先创建好的整型对象就是享元对象。
在Java String类的实现中,JVM开辟一块存储区专门存储字符串常量,这块存储区叫作字符串常量池,类似于Integer中的IntegerCache。不过,跟IntegerCache不同的是,它并非事先创建好需要共享的对象,而是在程序的运行期间,根据需要来创建和缓存字符串常量。
18年征途,追寻中国探月之旅访嫦娥五号探测器副总设计师张洪华来源人民周刊昔有嫦娥奔月,今有中国探月。上古的神话传说,在本世纪初成为现实,中国的探月工程在2004年正式立项。古老的中华文明在今朝跨越时空接力前行,18年来的一系列嫦娥工程为您揭
NASA局长妄称中国打着科研幌子上月球,是为了占领月球文李海军新年的第一天,美国就有人对华放炮,1月1日,美国国家航空航天局(NASA)局长比尔尼尔森对媒体称中美正处于一场太空竞赛,我们最好小心,不要让他们打着科学研究的幌子抵达月球上
90后情侣骑摩托环游中国!花光积蓄后,靠着贷款走完三条边境公路这是走吧网推送的第274个与众不同的旅者故事本期嘉宾安娜安娜,90后川妹子,四川德阳人,19岁开始徒步搭车背包旅行21省,骑自行车跨越过5省,和男友骑着一辆150cc的小摩托环游中
中国古代三大侍寝方法,发明者都是千古一帝中国古代三大侍寝方法,发明者都是千古一帝,做法却一个比一个离谱,让后宫嫔妃苦不堪言,那这三种侍寝方式究竟是啥?又为什么说它们奇葩至极呢?皇帝作为古代封建时期至高无上的存在,拥有众多
中国高校108吉林省曾经有所电影学院,比肩北影,为啥黄了?长春有新中国第一个电影制片厂,为啥没有电影大学呢?其实,吉林省曾经有一所电影学院,不过后来黄了。这是为什么呢?今天,每日汉字就和大家聊聊这所学校。长春市是有电影基础的。1937年,
古代仗打太多没钱怎么办,浅谈汉武帝时期的新财经政策如果您喜欢这篇作品,欢迎点击右上方关注。感谢您的鼓励与支持,希望能给您带来舒适的阅读体验。汉武帝刘彻是历史上颇受争议的皇帝,他的性格特点十分明显,既有雄才大略,具备高超的政治素养和
特斯拉挥出七伤拳,屠刀砍向蔚小理作者闫学功封面来源摄图网2023年第一个周五(1月6日),特斯拉官宣大降价,主力车型最高直降4。8万元。看似平静的中国车市,瞬间被这枚重磅炸弹炸开了锅。第二天,有特斯拉车主在门店拉
数字人民币扩围数字人民币规模化试点应用已悄然开启。近日,国际金融报记者了解到,继支付巨头入网试点城市扩围推出专属头像之后,在兔年新春来临之际,全国试点地区的消费者可用数字人民币发拜年红包置办年货
美股笑迎CPI!纳指涨1。763B家居涨68。6中新经纬1月12日电美股周三高开高走,纳指连续第四个交易日上涨。美国家居零售巨头3B家居涨68。6,据路透社报道,部分投资者猜测该公司可能成为潜在收购目标,该公司股价前一日收涨27
昔日网红,也慌了!作者飞天小女警曾经盲盒开盘自信满满的沙井海岸城,如今也慌了。这几天可以看到,尽管是西部超级网红小区,也要放下身段,大力安排营销。比如第一次开盘提供样板间第一次登记期间发布意向登记人
外资巨头大手笔增持美团中国基金报记者赵心怡据港交所1月11日公布的文件显示,摩根大通在1月5日增持约4047万股美团W(3690。HK),平均增持价格为每股190。3392港元,持股比例上升至5。21。