一、什么是享元模式?
享元模式的主要目的是实现对象的共享,当系统中有多个相同的对象,那么不需要实例化多个对象,只需要共享一个对象即可,这和对象池的概念类似,通常与工厂模式一起使用。比如有一家店做外卖,如果每以个订的食物都作为一个对象,那么几千单就有几千个食物对象,这是一种耗费内存的操作。事实上,一家店的菜单上食物一共也就几十种,这几千个订单完全可以共享相同的食物对象,这就是享元模式的一个应用。
二、享元模式框图
享元模式中有以下几个角色:
1. 抽象享元角色:具体享元类的基类,规定了需要被重写的接口方法
2. 具体享元角色:继承至抽象享元类
3. 享元工厂:负责管理和创建享元角色。工厂中存在一个享元角色的对象池,当客户端想要使用享元角色时,如果池中存在此对象,直接返回,否则创建后放入池中再返回。
4. 客户端:使用享元角色
二、享元模式的具体代码
在这里用还是用外卖的例子来说明。一家外卖店有以下食物:黄焖鸡米饭、红焖肥肠饭、铁板鱿鱼饭、海鲜煲仔饭、红烧大排面、片儿川、爆鳝面和腰花面。如果一天有上万个订单,使用了享元模式,那么就只有8个食物对象,不用每一个订单建立一个食物对象,食物对象完成了共享。
3.1 Order类,抽象订单类,内部有两个抽象方法:1. sell:接受订单收钱发货 2. getFood:看看客户点的啥东西
package designpatterns.flyweight;
/**
* Created by Olive on 2017/12/13.
* 外卖订单的抽象类
*/
public abstract class Order {
// 接收订单然后发送外卖
public abstract void sell();
// 获取外卖的种类,如黄焖鸡米饭,孜然牛肉饭,红焖大肠饭......
public abstract String getFood();
}
3.2 TakeawayOrder类,具体外卖订单类
package designpatterns.flyweight;
/**
* Created by Olive on 2017/12/13.
* 外面订单实现类
*/
public class TakeawayOrder extends Order{
private String food;
public TakeawayOrder(String food){
this.food = food;
}
@Override
public String getFood() {
return this.food;
}
@Override
public void sell() {
System.out.println("卖出了一碗 " + this.food);
}
}
3.3 FoodFactory类,食物工厂,内部维护了一个外卖订单池
package designpatterns.flyweight;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Olive on 2017/12/13.
* 食物的工厂类
*/
public class FoodFactory {
// 外卖订单池
private Map<String, Order> foodPool = new ConcurrentHashMap<String, Order>();
// 静态工厂
private static FoodFactory foodFactory = new FoodFactory();
public static FoodFactory getFoodFactory() {
return foodFactory;
}
public Order getOrder(String food) {
Order order = null;
if (foodPool.get(food) != null) {
order = foodPool.get(food);
} else {
order = new TakeawayOrder(food);
foodPool.put(food, order);
}
return order;
}
}
3.4 FoodHarvester类,食物收割者类,客户端调用
package designpatterns.flyweight;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Olive on 2017/12/13.
* 食物收割者类,他要点很多份外卖,但是他不会胖XD
*/
public class FoodHarvester {
// 外卖订单工厂
private static FoodFactory foodFactory;
// 订单列表
private static List<Order> orderList = new ArrayList<Order>();
public static void main(String[] args){
// 得到工厂实例
foodFactory = FoodFactory.getFoodFactory();
// 获得食物的订单,并且把订单加到订单列表中
orderList.add(foodFactory.getOrder("黄焖鸡米饭"));
orderList.add(foodFactory.getOrder("红焖肥肠饭"));
orderList.add(foodFactory.getOrder("铁板鱿鱼饭"));
orderList.add(foodFactory.getOrder("海鲜煲仔饭"));
orderList.add(foodFactory.getOrder("红烧大排面"));
orderList.add(foodFactory.getOrder("片儿川"));
orderList.add(foodFactory.getOrder("爆鳝面"));
orderList.add(foodFactory.getOrder("腰花面"));
// 他还想吃一碗肥肠饭和煲仔饭
orderList.add(foodFactory.getOrder("红焖肥肠饭"));
orderList.add(foodFactory.getOrder("铁板鱿鱼饭"));
for(Order order : orderList){
order.sell();
}
}
}
3.5 运行结果
卖出了一碗 黄焖鸡米饭
卖出了一碗 红焖肥肠饭
卖出了一碗 铁板鱿鱼饭
卖出了一碗 海鲜煲仔饭
卖出了一碗 红烧大排面
卖出了一碗 片儿川
卖出了一碗 爆鳝面
卖出了一碗 腰花面
卖出了一碗 红焖肥肠饭
卖出了一碗 铁板鱿鱼饭
Process finished with exit code 0