简介
享元模式时对象池的一种实现,用来尽可能减少内存的使用量,适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享、避免创建过多对象的效果,这样就可以有效的提升性能、避免内存移除等。
享元对象中的部分状态是可以共享的,可以共享的状态称之为内部状态,内部状态不会随着环境变化,不可共享的状态称之为外部状态,他们会随着环境的改变而改变,。在享元模式中会建立一个容器为map,它的键是享元对象的内部状态,他得值就是享元对象本身。客户端程序通过这个内部状态从享元工厂中获取享元对象,如果有缓存则使用缓存对象,否则创建一个享元对象并且存入容器中,这样一来就避免了创建过多对象的问题。
定义
使用享元对象可有效的支持大量细粒度的对象
使用场景
系统中存在大量相似的对象
细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份
需要缓冲池的场景
关键点
一个抽象享元对象—享元对象抽象基类或接口
一个具体享元对象—继承与抽象享元对象
一个工厂角色—享元工厂,负责管理享元对象池和创建享元对象
实现
/**
* 抽象享元角色
*/
public interface AbsTicket {
/**
* 享元对象共有行为
*/
public void showTicketInfo();
}
/**
* 具体的享元对象
*/
public class TrainTicket implements AbsTicket {
private String origin;
private String dest;
private String bunk;
private int price;
public TrainTicket(String origin, String dest, String bunk, int price) {
this.origin = origin;
this.dest = dest;
this.bunk = bunk;
this.price = price;
}
@Override
public void showTicketInfo() {
Log.i(getClass().getSimpleName(),
"起始站:" + origin + "-目的站:" + dest + ",铺位:" + bunk + ",价格:" + price);
}
}
/**
* 享元工厂
*/
public class TicketFactory {
static Map<String, AbsTicket> ticketMap = new HashMap<>();
public static AbsTicket getTicket(String origin, String dest) {
String key = origin + "-" + dest;
if (ticketMap.containsKey(key)) {
return ticketMap.get(key);
} else {
TrainTicket ticket = new TrainTicket(origin, dest, "软卧", 415);
ticketMap.put(key, ticket);
return ticket;
}
}
}
AbsTicket ticket = TicketFactory.getTicket("北京", "西安");
ticket.showTicketInfo();
AbsTicket ticket1 = TicketFactory.getTicket("北京", "西安贝");
ticket.showTicketInfo();
小结
优点
减少应用程序创建对象、降低程序内存的占用、增强程序的性能
缺点
提高了系统的复杂性,需要分离出内部状态和外部状态,同时保持内部状态的固化特性,不应随内部状态的变化而变化,否则导致系统逻辑混乱