享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型设计模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。它的核心结构有四个角色:抽象享元角色(AbstractFlyWeight)、具体享元角色(ConcreteFlyWeight)、享元工厂(FlyWeightFactory)、客户端(Client)。
(1) 抽象享元角色:为具体享元角色规定了必须实现的方法,在Java中可以是抽象类,可以是接口。
(2) 具体享元角色:实现抽象角色定义的方法。
(3) 享元工厂角色:生成FlyWeight角色的工厂,在工厂中生成的FlyWeight角色可以实现共享实例。
(4) 客户端角色:Client角色使用FlyWeightFactory来生成FlyWeight角色。
池化技术都是这种模式的实现,数据库连接池、线程池、字符串常量池等等。生活中也有很多这种例子,比如共享单车、共享充电宝、共享雨伞等等。接下来我们以共享充电宝为例展开讨论。
类图 示例抽象享元角色
public abstract class SharePortableBattery {
//0是未使用,1是使用中
protected int state = 0;
//租赁时长,单位分钟
protected long rentTime = 0;
abstract void rent(String userName);
abstract void back(long rentTime);
public void setState(int state){
this.state = state;
}
public int getState() {
return state;
}
public long getRentTime() {
return rentTime;
}
}
具体享元角色
public class MonsterSharePortableBattery extends SharePortableBattery{
//充电宝id
private int batteryId;
//使用时长
private long rentTime;
public MonsterSharePortableBattery(int batteryId) {
this.batteryId = batteryId;
}
public int getBatteryId(){
return batteryId;
}
public void setRentTime(long rentTime){
this.rentTime = rentTime;
}
public long getRentTime(){
return rentTime;
}
@Override
void rent(String userName) {
SharePortableBatteryFactory.getInstance().setState(batteryId, 1);
System.out.println(userName + "租赁" + batteryId + "号 充电宝!");
}
@Override
void back(long rentTime) {
SharePortableBatteryFactory.getInstance().setRentTime(batteryId, rentTime);
System.out.println(batteryId + "号 充电宝归还!");
}
}
享元工厂
public class SharePortableBatteryFactory {
private static SharePortableBatteryFactory instance = new SharePortableBatteryFactory();
private static List pool = new ArrayList<>();
public static SharePortableBatteryFactory getInstance() {
return instance;
}
static{
for (int i = 0; i < 4; i++) {
pool.add(new MonsterSharePortableBattery(i));
}
}
public MonsterSharePortableBattery getBattery() {
List sortedPool = pool.stream().filter(v -> v.getState() == 0).sorted(Comparator.
comparing(MonsterSharePortableBattery::getRentTime)).collect(Collectors.toList());
if(!CollectionUtils.isEmpty(sortedPool)){
return sortedPool.get(0);
}
return null;
}
public void setRentTime(int batteryId, long rentTime) {
for (MonsterSharePortableBattery battery : pool) {
if (battery.getBatteryId() == batteryId){
battery.setRentTime(battery.getRentTime() + rentTime);
battery.setState(0);
break;
}
}
}
public void setState(int batteryId, int state) {
for (MonsterSharePortableBattery battery : pool) {
if (battery.getBatteryId() == batteryId){
battery.setState(state);
break;
}
}
}
}
客户端
public static void main(String[] args) {
SharePortableBattery battery1 = SharePortableBatteryFactory.getInstance().getBattery();
battery1.rent("关羽");
battery1.back(20);
SharePortableBattery battery2 = SharePortableBatteryFactory.getInstance().getBattery();
battery2.rent("张飞");
battery2.back(10);
SharePortableBattery battery3 = SharePortableBatteryFactory.getInstance().getBattery();
battery3.rent("赵云");
battery3.back(15);
SharePortableBattery battery4 = SharePortableBatteryFactory.getInstance().getBattery();
battery4.rent("马超");
battery4.back(35);
SharePortableBattery battery5 = SharePortableBatteryFactory.getInstance().getBattery();
battery5.rent("黄忠");
battery5.back(40);
System.out.println(battery5 == battery2);
}
我们在享元工厂里初始化了4个充电宝享元实例,所以第5个人租赁和第2个人租赁得到的充电宝实例是一致的。



