享元模式
享元模式(Flyweight Pattern):又称之为蝇量模式,是对象池的一种实现。主要用于减少创建对象的数量,以减少内存占用和提高性能。类似于我们的数据库连接池和线程池。
这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
示例:我们通过购买火车票为例,来举例说明...
package cn.liangyy.flyweight.one;
/**
* 车票接口
*/
public interface ITicket {
/**
* 查询车票信息
*/
void info();
}
复制代码
package cn.liangyy.flyweight.one;
/**
* 火车票类
*/
public class TrainTicket implements ITicket {
private String from; //起点
private String to; //终点
public TrainTicket(String from,String to){
this.from = from;
this.to = to;
}
/**
* 查询车票信息
*/
@Override
public void info() {
System.out.println(from + "-->" + to + ":硬座:100元,硬卧:200元");
}
}
复制代码
package cn.liangyy.flyweight.one;
import java.util.HashMap;
import java.util.Map;
/**
* 工厂类
* 管理享元对象,使用一个Map来存储对象,把火车票的起点和终点作为key,
* 如果存在就取出来,否则就创建新对象,并且加到Map中。
*/
public class TicketFactory {
//缓存对象
private static Map<String,ITicket> CACHE_POOL = new HashMap<>();
public static ITicket getTicketInfo(String from,String to){
String key = from + "-->" + to;
//如果对象存在缓存
if (TicketFactory.CACHE_POOL.containsKey(key)){
System.out.println("使用缓存");
return TicketFactory.CACHE_POOL.get(key);
}
//对象不存在缓存则创建一个对象,并加入缓存
System.out.println("未使用缓存");
ITicket ticket = new TrainTicket("成都","西宁");
CACHE_POOL.put(key,ticket);
return ticket;
}
}
复制代码
package cn.liangyy.flyweight.one;
/**
* 享元模式-测试
*/
public class TestTicket {
public static void main(String[] args) {
//首次创建对象
ITicket ticket = TicketFactory.getTicketInfo("成都","西宁");
ticket.info();
//使用缓存
ticket = TicketFactory.getTicketInfo("成都","西宁");
ticket.info();
//换了终点,,无法使用缓存
ticket = TicketFactory.getTicketInfo("成都","上海");
ticket.info();
}
}
复制代码
看到这儿,大家都会觉得这不就是一个简单的缓存使用嘛?确实如此,享元模式的核心思想就是使用缓存,它看起来和单例有点相似,单例模式关注的是整个对象只有一个实例,而享元模式关注的是状态,也就是说,同一个类中,只有状态一致。比如上述例子中成都到西宁的火车票,这就属于状态一致,所以使用缓存,而成都到上海又是另一个状态,所以无法使用缓存。那么大家会有疑问:享元模式的状态到底是什么呢?
享元模式的状态分为两种:
前面的例子中,我们可以把实例对象划分一下,比如上面车票的对象,可以把 from 和 to 两个属性作为可共享状态,不可改变。然后再新增一个属性用来对应座位,这个就属于外部状态。
状态示例:我们通过内部状态和外部状态改造上面的示例...
package cn.liangyy.flyweight.two;
/**
* 车票接口
*/
public interface IShareTicket {
/**
* 获取车票信息
*/
void info();
/**
* 设置车票座位
* @param seatType
*/
void setSeat(String seatType);
}
复制代码
package cn.liangyy.flyweight.two;
import java.math.BigDecimal;
/**
* 火车票类
*/
public class TrainShareTicket implements IShareTicket {
private String from; //内部状态
private String to; //内部状态
private String seatType = "站票"; //外部状态
public TrainShareTicket(String from, String to) {
this.from = from;
this.to = to;
}
/**
* 获取车票信息
*/
@Override
public void info() {
System.out.println(from + "-->" + to + ":" + seatType + this.getPrice(seatType));
}
/**
* 设置车票座位
*
* @param seatType
*/
@Override
public void setSeat(String seatType) {
this.seatType = seatType;
}
//获取不同座位的价格
private BigDecimal getPrice(String seatType) {
BigDecimal value = null;
switch (seatType) {
case "硬座":
value = new BigDecimal("100");
break;
case "硬卧":
value = new BigDecimal("200");
break;
default:
value = new BigDecimal("50");
}
return value;
}
}
复制代码
package cn.liangyy.flyweight.two;
import java.util.HashMap;
import java.util.Map;
/**
* 工厂类
* 管理享元对象,使用一个Map来存储对象,把火车票的起点和终点作为key,
* 如果存在就取出来,否则就创建新对象,并且加到Map中。
*/
public class TicketShareFactory {
//存储缓存对象
private static Map<String,IShareTicket> CACHE_POOL = new HashMap<>();
public static IShareTicket getTicketInfo(String from,String to){
String key = from + "-->" + to;
//如果对象存在缓存
if (TicketShareFactory.CACHE_POOL.containsKey(key)){
System.out.println("使用缓存");
return TicketShareFactory.CACHE_POOL.get(key);
}
//对象不存在缓存则创建一个对象,并加入缓存
System.out.println("未使用缓存");
IShareTicket ticket = new TrainShareTicket(from,to);
CACHE_POOL.put(key,ticket);
return ticket;
}
}
复制代码
package cn.liangyy.flyweight.two;
/**
* 享元模式-测试
*/
public class TestShareTicket {
public static void main(String[] args) {
IShareTicket ticket = TicketShareFactory.getTicketInfo("成都","西宁");
ticket.setSeat("硬座"); //外部状态
ticket.info(); //首次创建对象
ticket = TicketShareFactory.getTicketInfo("成都","西宁");
ticket.setSeat("硬卧"); //外部状态
ticket.info(); //外部状态改变了,但是内部状态共享,依然可以使用缓存
}
}
复制代码
现在我们可以看到,将状态分离之后,外部状态的修改并不影响内部状态,也就是对象依然可以被缓存。
享元模式适用场景
享元模式优点减少对象的创建,降低了系统中对象的数量,故而可以降低系统的使用内存,提高效率。
享元模式缺点
评论