文章目录
享元模式情景
- 享元模式情景
- 享元模式实战
- 不使用享元模式的写法
- 使用享元模式的写法
享元模式主要在于共享通用对象,减少内存的使用,提升系统的访问效率。而这部分共享对象通常比较耗费内存或者需要查询大量接口或者使用数据库资源,因此统一抽离作为共享对象使用。
享元模式实战模拟在商品秒杀场景下使用享元模式查询优化. 商品活动信息是不变的, 变化的是库存信息.
不使用享元模式的写法模拟活动信息和库存信息都从数据库中查询. 创建tutorials-14.0-0 模块 创建Activity活动类
@Data
public class Activity {
private Long id; // 活动ID
private String name; // 活动名称
private String desc; // 活动描述
private Date startTime; // 开始时间
private Date stopTime; // 结束时间
private Stock stock; // 活动库存
}
创建库存类Stock
@Data
public class Stock {
private int total; // 库存总量
private int used; // 库存已用
public Stock(int total, int used) {
this.total = total;
this.used = used;
}
}
创建ActivityController, 实现活动信息和库存的查询. 此处模拟的是从数据库查询活动和库存信息.
public class ActivityController {
public Activity queryActivityInfo(Long id) {
// 模拟从数据库中获取接口信息
Activity activity = new Activity();
activity.setId(10001L);
activity.setName("图书嗨乐");
activity.setDesc("图书优惠券分享激励分享活动第二期");
activity.setStartTime(new Date());
activity.setStopTime(new Date());
activity.setStock(new Stock(1000,1));
return activity;
}
}
使用享元模式的写法
享元模式类图. ActivityFactory 构建了享元工厂, 用一个map结构来进行缓存活动信息. ActivityFactory 代码如下
public class ActivityFactory {
static Map activityMap = new HashMap();
public static Activity getActivity(Long id) {
Activity activity = activityMap.get(id);
if (activity == null) {
activity = new Activity();
activity.setId(1000L);
activity.setName("618");
activity.setDesc("618 数码电器大促销");
activity.setStartTime(new Date());
activity.setStopTime(new Date());
activityMap.put(id, activity);
}
return activity;
}
}
RedisUtils 模拟了定时任务来增加使用的库存.
public class RedisUtils {
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
private AtomicInteger stock = new AtomicInteger(0);
public RedisUtils() {
scheduledExecutorService.scheduleAtFixedRate(()->{
stock.addAndGet(1);
// 0.1秒库存变化一次
}, 0, 100000, TimeUnit.MICROSECONDS);
}
public int getStockUsed() {
return stock.get();
}
}
ActivityController 如下. 从ActivityFactory中获取活动信息. 从RedisUtils 中获取库存信息.
public class ActivityController {
private RedisUtils redisUtils = new RedisUtils();
public Activity queryActivityInfo(Long id) {
Activity activity = ActivityFactory.getActivity(id);
Stock stock = new Stock(1000, redisUtils.getStockUsed());
activity.setStock(stock);
return activity;
}
}
测试类 (结果)
public class ApiTest {
private Logger logger = LoggerFactory.getLogger(ApiTest.class);
private ActivityController activityController = new ActivityController();
@Test
public void test_queryActivityInfo() throws InterruptedException {
for (int i = 0; i
关注
打赏