使用享元模式实现资源共享池
本节我们使用享元模式来实现资源共享池。举个例子,每年春节为了买到一张回家的火车票,大家都大费周章。为了解决这一问题,12306 网站提供了自动查票的功能。如果开启自动查票的功能,则系统会将我们填写的信息缓存起来,然后定时查询余票信息。
在买票的时候,我们肯定要查询一下有没有我们需要的车票。假设一张火车票包含出发站、目的站、价格、座位类别等信息。现在要求编写查询火车票的模拟代码。
比如要求可以通过出发站、目的站来查询火车票的相关信息,那么只需构建出火车票类对象,向用户提供一个查询出发站、目的站的接口进行查询即可。
首先创建 Ticket 接口。
其实更好的做法应该是缓存该火车票对象,然后提供给其他查询请求复用,这样一个对象就足以支撑数以千计的查询请求,内存完全无压力。使用享元模式就可以很好地解决这个问题。
下面我们继续优化代码,只需要在 TicketFactory 类中进行更改,增加缓存机制。
其中,Ticket 是抽象享元角色,TrainTicket 是具体享元角色,TicketFactory 是享元工厂。有些小伙伴一定会有疑惑了,这不就是注册式单例模式吗?虽然在结构上很像,但是享元模式的重点在结构上,而不是在创建对象上。后面结合享元模式在 JDK 源码中的应用,大家应该就能彻底明白了。
在买票的时候,我们肯定要查询一下有没有我们需要的车票。假设一张火车票包含出发站、目的站、价格、座位类别等信息。现在要求编写查询火车票的模拟代码。
比如要求可以通过出发站、目的站来查询火车票的相关信息,那么只需构建出火车票类对象,向用户提供一个查询出发站、目的站的接口进行查询即可。
首先创建 Ticket 接口。
public interface Ticket { void showInfo(String bunk); }然后创建 TrainTicket 类实现 Ticket 接口。
public class TrainTicket implements Ticket { private String from; private String to; private int price; public TrainTicket(String from, String to) { this.from = from; this.to = to; } @Override public void showInfo(String bunk) { this.price = new Random().nextInt(500); System.out.println(this.from + "->" + this.to + ":" + bunk + "价格:" + price + "元"); } }接着创建 TicketFactory 类。
public class TicketFactory { public static Ticket queryTicket(String from,String to){ return new TrainTicket(from,to); } }最后编写客户端代码如下:
public static void main(String[] args) { Ticket ticket = TicketFactory.queryTicket("北京西","石家庄"); ticket.showInfo("硬座"); }运行结果如下:
首次查询,创建对象:北京西->石家庄
北京西->石家庄:硬座价格:450元
其实更好的做法应该是缓存该火车票对象,然后提供给其他查询请求复用,这样一个对象就足以支撑数以千计的查询请求,内存完全无压力。使用享元模式就可以很好地解决这个问题。
下面我们继续优化代码,只需要在 TicketFactory 类中进行更改,增加缓存机制。
public class TicketFactory { private static Map<String, Ticket> sticketPool = new ConcurrentHashMap<String, Ticket>(); public static Ticket queryTicket(String from, String to) { String key = from + "->" + to; if (TicketFactory.sticketPool.containsKey(key)) { System.out.println("使用缓存:" + key); return TicketFactory.sticketPool.get(key); } System.out.println("首次查询,创建对象:" + key); Ticket ticket = new TrainTicket(from, to); TicketFactory.sticketPool.put(key, ticket); return ticket; } }测试代码如下:
public class Test { public static void main(String[] args) { Ticket ticket = TicketFactory.queryTicket("北京西","石家庄"); ticket.showInfo("硬座"); Ticket ticket2 = TicketFactory.queryTicket("北京西","石家庄"); ticket.showInfo("软座"); Ticket ticket3 = TicketFactory.queryTicket("北京西","石家庄"); ticket.showInfo("硬卧"); } }运行结果如下:
首次查询,创建对象:北京西->石家庄
北京西->石家庄:硬座价格:48元
使用缓存:北京西->石家庄
北京西->石家庄:软座价格:98元
使用缓存:北京西->石家庄
北京西->石家庄:硬卧价格:118元
其中,Ticket 是抽象享元角色,TrainTicket 是具体享元角色,TicketFactory 是享元工厂。有些小伙伴一定会有疑惑了,这不就是注册式单例模式吗?虽然在结构上很像,但是享元模式的重点在结构上,而不是在创建对象上。后面结合享元模式在 JDK 源码中的应用,大家应该就能彻底明白了。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算