李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
【转载】设计模式之享元模式
Leefs
2020-01-08 AM
6986℃
2条
# 【转载】设计模式之享元模式 ### 前言 在大学时代,估计每个人都去图书馆借过书。借书的流程很简单,如果书架上有这本书直接拿走,到借阅机上借阅就好了,如果没有,可以到图书管理处去拿一本新书。对于整个图书馆来说,书其实就是共享的,但是我们会发现其实每次借的书都是那些破旧一点的书,而不是新书,这是因为学生太多了,如果我们每一次借书都拿出来一本新书,那整个图书馆估计会放不下,对于我们借书的流程和图书共享的方式就是享元模式。 ### 一、认识享元模式 #### 1、概念 > 如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一个使用都创建新的对象。目的是提高系统性能。 上面的概念乍一听好像单例模式,其实不是,单例模式只保存一个对象,但是这里可以有很多个不同对象,但是每个对象只有一个实例而已。也就是说享元模式使用了单例模式。 #### 2、例子解释 在文章一开始其实我们就讲了这个例子,现在我们梳理一下,再次用这个例子来解释享元模式。张三去借书,然后阅读完了还回去了,过一段时间发现还是不懂,又去借了同样的书,但是这本书其实和上一次借的书是同一本。李四也去借书,发现书架上没有,就去图书管理员那边拿出来了一本全新的书。这就是享元模式。 **享元模式的主要角色由享元工厂、抽象享元、具体享元类几部分组成。** 我们使用这个例子以类图的角度来观察一下: ![享元模式image01.jpg][1] 从上面这个例子我们可以看到,这里其实有四个角色: (1)享元工厂(Library):用于创建具体享元类,维护相同的享元对象。当请求对象已经存在时,直接返回对象,不存在时,在创建对象。在例子中的解释就是图书馆,保存了所有的书,当学生借书时,有就拿走,没有买一本新书。这里面其实是使用了单例模式的。 (2)抽象享元(Book):定义需要共享的对象业务接口。享元类被创建出来总是为了实现某些特定的业务逻辑。 (3)具体享元(ConcreteBook):实现抽象享元类的接口,完成某一具体逻辑。在这里表示可以被借走。 在这里享元工厂是享元模式的核心,它需要确保系统可以共享相同的对象。它会维护一个对象列表,当我们想要获取享元类时,如果请求的享元类已经被创建,则直接返回已有的享元类:若没有,则创建一个新的享元对象,并将它加入到维护队列中。 下面我们使用代码来实现一下吧。 ### 二、代码实现 第一步:定义抽象享元类(Book) ```java public interface Book{ public void borrow(); } ``` 第二步:定义具体享元类(ConcreteBook) ```java public class ConcreteBook implements Book{ //被借走的书名 private String name; public ConcreteBook(String name){ this.name=name; } @Override public void borrow(){ System.out.println("图书馆借出一本书,书名为:" + this.name ); } } ``` 第三步:享元工厂(Library) ```java public class Library{ //图书馆维护一个图书列表 private Map
bookPools = new HashMap
(); private static Library factory = new Library(); //图书馆只有一个 public static Library getInstance(){ return factory; } //图书馆外借图书 public Book libToBorrow(String bookName){ Book order = null; //如果书架有,直接借出 if (bookPools.containsKey(bookName)) { order = bookPools.get(bookName); } //如果书架没有,那就调进来一本新书 else{ order = new ConcreteBook(bookName); bookPools.put(bookName, order); } return order; } //图书馆书架上的书的数量 public int getAllBookSize(){ return bookPools.size(); } } ``` 第四步:模拟学生去借书 ``` java public class Student { //图书馆书架上的书 private static List
books = new ArrayList
(); private static Library library; public static void main(String[] args) { library = Library.getInstance(); studentBorrow("java编程思想"); studentBorrow("java核心卷一"); studentBorrow("java从入门到精通"); System.out.println("后两本没学会,又借了一次 "); studentBorrow("java核心卷一"); studentBorrow("java从入门到精通"); //把每一本书借出去 for (Book book : books) { book.borrow(); } //输出一些学生一共借多少本书 System.out.println("学生一共借了 " + books.size() + " 本书! "); //输出一下图书馆一共借出多少本书 System.out.println("图书馆实际借出" + library.getAllBookSize() + " 本书"); } private static void studentBorrow(String bookName) { books.add(library.libToBorrow(bookName)); } } ``` 在上面其实学生一共借了5次书,但是有两本是重复的,所以对于图书馆来说,其实是借出去了三本书。最后我们看一下输出结果吧: ```java //图书馆借出去一本书,书名为:java编程思想 //图书馆借出去一本书,书名为:java核心卷一 //图书馆借出去一本书,书名为:java从入门到精通 //后两本没学会,又借了一次 //图书馆借出去一本书,书名为:java核心卷一 //图书馆借出去一本书,书名为:java从入门到精通 //学生一共借了 5 本书! //图书馆实际借出了 3 本书 ``` 以上就是享元模式的代码实现,其实在这里最为关键的就是享元工厂类。享元模式的思想也主要在这个类中去体现。最后我们把享元模式和其他的模式进行一个对比分析。 ### 三、分析享元模式 #### 1、享元模式的优点 (1)节省内存空间,对于可重复的对象只会被创建一次,对象比较多时,就会极大的节省空间。 (2)提高效率,由于创建对象的数量减少,所以对系统内存的需求也减小,使得速度更快,效率更高。 ### 2、享元模式的缺点 其实对于享元类有内部状态和外部状态,其区分就是图书馆的书一部分可以外借(外部状态),一部分不可外借(内部状态),两个状态的划分对于书籍管理来说优点复杂化了。 #### 3、享元模式与单例模式的区别 (1)享元设计模式是一个类有很多对象,而单例是一个类仅一个对象。 (2)享元模式是为了节约内存空间,提升程序性能,而单例模式则主要是出于共享状态的目的。 OK,以上就是享元模式,在使用的时候只需要记住享元模式的核心思想,然后根据自己的业务需求来选择,因为大大多情况下都不会使用一种设计模式,而是多种设计模式的组合。 *附:[原文链接地址](https://www.jianshu.com/p/2529119de443)* [1]: https://lilinchao.com/usr/uploads/2020/01/1858106664.jpg
标签:
Java
,
设计模式
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://www.lilinchao.com/archives/393.html
上一篇
容器深入研究--Map生成器
下一篇
Docker迁移与备份
取消回复
评论啦~
提交评论
已有 2 条评论
茂林
大佬大佬·
回复
2020-01-08 15:52
Leefs
博主
@茂林
哈哈,转发过来的文章就是香
回复
2020-01-09 08:29
栏目分类
随笔
2
Java
326
大数据
229
工具
35
其它
25
GO
48
NLP
8
标签云
SpringCloudAlibaba
pytorch
SpringBoot
Git
数学
SpringCloud
Kubernetes
递归
容器深入研究
Flink
RSA加解密
Map
Yarn
nginx
持有对象
微服务
Spark RDD
Hadoop
排序
Ubuntu
Hbase
Spring
队列
Netty
VUE
JavaWeb
Livy
散列
国产数据库改造
Java阻塞队列
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
大佬大佬·
哈哈,转发过来的文章就是香