享元模式
前言
– 场景:
内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的
对象,我们可以通过享元模式,节省内存。
– 核心:
享元模式以共享的方式高效地支持大量细粒度对象的重用。
享元对象能做到共享的关键是区分了内部状态和外部状态。
内部状态:可以共享,不会随环境变化而改变
外部状态:不可以共享,会随环境变化而改变
– 享元模式实现:
- FlyweightFactory享元工厂类
创建并管理享元对象,享元池一般设计成键值对 - FlyWeight抽象享元类
通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。 - ConcreteFlyWeight具体享元类
为内部状态提供成员变量进行存储 - UnsharedConcreteFlyWeight非共享享元类
不能被共享的子类可以设计为非共享享元类
一、具体实现
以咖啡店为例,咖啡店有几种口味的咖啡,拿铁、摩卡、卡布奇诺…如果店家接到订单要十几杯咖啡,显然咖啡的口味可以设置为共享的,而不必每一杯单独生成。
1.抽象享元对象
/**
* 抽象享元对象
*/
public abstract class Order {
//卖出的动作
public abstract void sell();
}
2.具体享元角色
/**
*具体享元角色
*/
public class FlavorOrder extends Order{
public String flavor;
//获取咖啡口味
public FlavorOrder(String flavor) {
this.flavor = flavor;
}
@Override
public void sell() {
System.out.println("卖出一杯"+flavor+"的咖啡");
}
}
3.享元工厂角色
/**
* 享元工厂角色
*/
public class FlavorFactory {
private Map<String,Order> flavorPool = new HashMap<>();
//静态工厂,负责生成订单
private static FlavorFactory flavorFactory = new FlavorFactory();
private FlavorFactory(){}
public static FlavorFactory getInstance(){
return flavorFactory;
}
public Order getOrder(String flavor){
Order order = null;
//实现享元模式关键
if(flavorPool.containsKey(flavor)){
order= flavorPool.get(flavor);
}else {
order = new FlavorOrder(flavor);
flavorPool.put(flavor,order);
}
return order;
}
public int getTotalFlavorMade(){
return flavorPool.size();
}
}
4.测试类
/**
* 客户类
*/
public class Client {
//下订单
private static List<Order> orders = new ArrayList<>();
//订单对象生成工厂
private static FlavorFactory flavorFactory;
//增加订单
private static void takeOrders(String flavor){
orders.add(flavorFactory.getOrder(flavor));
}
public static void main(String[] args) {
flavorFactory = FlavorFactory.getInstance();
//增加订单
takeOrders("摩卡");
takeOrders("卡布奇诺");
takeOrders("香草星冰乐");
takeOrders("拿铁");
takeOrders("拿铁");
takeOrders("摩卡");
//卖咖啡
for (Order order : orders) {
order.sell();
}
System.out.println("客户一共买了"+orders.size()+"杯咖啡");
System.out.println("共生成了"+flavorFactory.getTotalFlavorMade()+"个对象");
}
}
结果:
二、应用场景
- 线程池、数据库连接池。
- String类的设计也是享元模式
总结
- 优点
1.极大减少内存中对象的数量
2.相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
3.外部状态相对独立,不影响内部状态 - 缺点
1.模式较复杂,使程序逻辑复杂化
2.为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长。用时间换取了空间