使用Quartz写一个简单的计时器,再使用观察者模式实现秒杀按钮启动的案例
题目
在某些重要的场景下,电商会开展定时秒杀活动,假设在6.18活动中携程网会对站内多种商品在同一时刻启动秒杀活动,请使用观察者模式,完成上述功能的设计类图和源码。
解题过程
分析
在这个案例里,我没有写出相应的界面,所有的功能都是使用类模拟相对应的模块,重点在于观察者模式的使用上。先上类图。这里我用Quartz写了一个简单的计时器,通过Cron表达式对秒杀时间进行设置。当系统到达秒杀的时间时,秒杀按钮才开启秒杀。然后封装两个ConcreteButton的具体观察者类来模拟秒杀模块的功能。
上面的类图大致分为两个部分:其中的类QuartzSeckill主要与Client搭配实现计时器的功能,下面的5个类为观察者模式的实现,具体如下:
Seckill:目标类(Subject),作为秒杀抽象目标类,其中的notifyseckill()为抽象通知方法;
SeckillTime:具体目标类(ConcreteSubject),通过继承Seckill类,实现具体的通知方法;
SeckillButton:观察者类(Observer):对Seckill类的改变做出反应,声明了更新数据的抽象方法response();
ConcreteButton、ConcreteButtonall:具体观察者类(ConcreteObserver),两个类的功能相同,都是实现SeckillButton类中response()的具体方法,只是两个类的一些方法上存在差异。
实现
以下是观察者模式的各个类,代码中含有解释的一些地方不再过多赘述:
Seckill.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import java.util.ArrayList;
public abstract class Seckill { protected ArrayList<SeckillButton> buttons = new ArrayList<SeckillButton>(); public void attach(SeckillButton button){ buttons.add(button); } public void detach(SeckillButton button){ buttons.remove(button); } public abstract void notifyseckill(); } 12345678910111213141516171819202122
|
SeckillTime.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public class SeckillTime extends Seckill{
public boolean SeckillStart; @Override public void notifyseckill() { System.out.println("618携程网的秒杀活动开始!"); System.out.println("------------------"); for(SeckillButton button:buttons){ button.response(); } } } 1234567891011121314151617
|
SeckillButton.java:
1 2 3 4 5 6 7 8
|
public interface SeckillButton { void response(); } 1234567
|
ConcreteButton.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class ConcreteButton implements SeckillButton { private String name; public ConcreteButton(String name) { this.name =name; } public String getName() { return name; } @Override public void response() { System.out.println(name+"按钮开始秒杀!"); } } 1234567891011121314151617181920
|
ConcreteButtonall.java
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public class ConcreteButtonall implements SeckillButton {
@Override public void response() { System.out.println("全网按钮开始秒杀!"); } } 123456789101112
|
做到这里其实已经基本实现了观察者模式了,如果不添加计时器,只需要再写一个以下的客户端类对各个类进行调用即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Client { public static void main(String[] args){ Seckill seckill = new SeckillTime(); SeckillButton planeButton = new ConcreteButton("机票"); SeckillButton travelButton = new ConcreteButton("门票"); SeckillButton allButton = new ConcreteButtonall(); seckill.attach(planeButton); seckill.attach(travelButton); seckill.attach(allButton); seckill.notifyseckill(); } 1234567891011121314
|
Quartz设计计时器
但是这里如果我们要用Quartz写一个计时器,就要将上面的客户端类进行修改。先说一下Quartz的简单运用。
首先,需要导入Quartz需要的包。如果创建的项目是maven项目的话,可以在pom.xml文件中直接加上Quartz的依赖即可。
1 2 3 4 5 6 7 8
| <dependencies> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency> </dependencies> 1234567
|
如果不想建立maven项目,也可以自行下载jar包进行导入即可,我这里创建的是Web项目,所以直接将jar包导入到lib文件中即可,如果不是Web项目只需要自行创建一个lib文件就行,由于比较简单,这里就不说明了。
依赖的jar包可在这里http://www.quartz-scheduler.org/下载
如果网速不行可上https://www.jb51.net/softs/539791.html。
实际用到的jar包有三个:quartz-2.2.1.jar,c3p0-0.9.1.1.jar,slf4j-api-1.6.6.jar
Quartz的简单理解就是在什么时间去做什么事情,它的使用思路分为三步:
- job - 任务 - - 你要做什么事?
- Trigger - 触发器 - - 你什么时候去做?
- Scheduler - 任务调度 - - 你什么时候需要去做什么事?
其中第3部是对前两步的整合,使其能合到一起,产生作用。要做一个开启秒杀按钮的计时器,我们就要先创建一个Job类,Job类中放的就是我们要做的事,这里我们需要它到预订的时间打开秒杀按钮,在观察者模式中也就是将上面客户端类的中目标类的通知方法notifyseckill()放到这个类中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public class QuartzSeckill implements Job {
@Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("当前时间为:"+new Date()); Seckill seckill = new SeckillTime(); SeckillButton planeButton = new ConcreteButton("机票"); SeckillButton travelButton = new ConcreteButton("门票"); SeckillButton allButton = new ConcreteButtonall(); seckill.attach(planeButton); seckill.attach(travelButton); seckill.attach(allButton); seckill.notifyseckill(); } } 123456789101112131415161718192021222324
|
再写一个客户端类Client,分别创建Job、Trigger、Scheduler对象,完成对代办事务设置什么时间,要做的事情,以及将两者整合到一起的工作。具体看代码中的注解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import java.util.Date; import java.util.Scanner;
import org.quartz.CronScheduleBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.impl.StdSchedulerFactory;
public class Client {
public static void main(String[] args) throws Exception {
String[] str = new String[5]; System.out.print("请设置秒杀时间(月 日 时 分 秒):"); Scanner in = new Scanner(System.in); for (int i = 0; i <5 ; i++) { str[i]=in.next(); } System.out.println("618携程网的秒杀活动将于2020年"+str[0]+"月"+str[1]+"日"+str[2]+"点"+str[3]+"分"+str[4]+"秒开始"); System.out.println("当前时间为:"+new Date());
JobDetail job = JobBuilder.newJob(QuartzSeckill.class).build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule(str[4]+" "+str[3]+" "+str[2]+" "+str[1]+" "+str[0]+" ? *")).build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.scheduleJob(job, trigger); scheduler.start(); } } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
|
运行结果
以上就是运用Quartz和观察者模式对于启动秒杀按钮案例的所有内容,仅作为学习笔记做记录。如果能帮助到你,是我荣幸。有错误的地方也请大家帮忙指正,谢谢!