现在假设我们有两种类型的订单,汽车服务订单和商城配件订单
我们的抽象订单接口为
代码语言:javascript复制public interface Order {
public void makeOrder(Order order);
}
抽象订单工厂接口为
代码语言:javascript复制public interface OrderFactory {
public Order createOrder();
}
现有具体的汽车服务类型订单
代码语言:javascript复制@Data
@AllArgsConstructor
@NoArgsConstructor
@ServiceOrderVersion(value = 1)
@RequiredArgsConstructor
public class ServiceOrder implements Order {
private Long id;
@NonNull
private String code;
@NonNull
private Store store;
@NonNull
private ProviderService service;
@NonNull
private Car car;
@NonNull
private Date serviceDate;
@NonNull
private String contact;
@NonNull
private String contactTel;
private AppUser user;
@NonNull
private String content;
private int status;
private Date createDate;
@Override
public void makeOrder(Order order) {
ServiceOrderDao serviceOrderDao = SpringBootUtil.getBean(ServiceOrderDao.class);
IdService idService = SpringBootUtil.getBean(IdService.class);
((ServiceOrder)order).setId(idService.genId());
AppUser loginAppUser = AppUserUtil.getLoginAppUser();
AppUser user = new AppUser();
user.setId(loginAppUser.getId());
user.setUsername(loginAppUser.getUsername());
((ServiceOrder)order).setUser(user);
((ServiceOrder)order).setStatus(1);
((ServiceOrder)order).setCreateDate(new Date());
serviceOrderDao.save((ServiceOrder) order);
}
}
@ServiceOrderVersion版本号如下
代码语言:javascript复制@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceOrderVersion {
int value();
}
商城配件订单略
具体汽车服务工厂,我们将其注入Spring容器,不需要每次下单的时候都去扫描包
代码语言:javascript复制@Component
public class ServiceOrderFactory implements OrderFactory {
private Set<Class<?>> classes = ClassUtil.getClassSet("com.cloud.ownercar.domain");
@Override
public Order createOrder() {
Object instance = null;
try {
//过滤有@OrderVersion标签的类
instance = classes.stream().filter(clazz -> clazz.isAnnotationPresent(ServiceOrderVersion.class))
//过滤实现了Order接口的类
.filter(clazz -> Order.class.isAssignableFrom(clazz))
//找出版本号大的类,并实例化为对象
.max(Comparator.comparingInt(clazz -> clazz.getAnnotation(ServiceOrderVersion.class).value()))
.get().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (Order) instance;
}
}
具体配件工厂略
Controller如下,用传递的内容来判断是哪种类型的订单,并给抽象订单工厂来获取具体的订单工厂,通过具体的订单工厂来生成订单服务,完成下单功能。考虑到线程安全问题,所以要加ThreadLocal进行保护。
代码语言:javascript复制@Slf4j
@RestController
public class OrderController {
private ThreadLocal<OrderFactory> orderFactory = new ThreadLocal<>();
private ThreadLocal<Order> orderService = new ThreadLocal<>();
@Transactional
@SuppressWarnings("unchecked")
@PostMapping("/makeeorder")
public Result<String> makeOrder(@RequestBody String orderStr) {
log.info(orderStr);
Order order = setOrderFactory(orderStr);
orderService.get().makeOrder(order);
return Result.success("下单成功");
}
/**
* 判断是哪一种类型的订单来获取哪一种类型的具体订单工厂
* @param orderStr
* @return
*/
private Order setOrderFactory(String orderStr) {
Order order = null;
if (orderStr.contains("service")) {
order = JSON.parseObject(orderStr, ServiceOrder.class);
}else if (orderStr.contains("product")) {
order = JSON.parseObject(orderStr, ProductOrder.class);
}
if (order instanceof ServiceOrder) {
this.orderFactory.set(SpringBootUtil.getBean(ServiceOrderFactory.class));
}else if (order instanceof ProductOrder) {
this.orderFactory.set(SpringBootUtil.getBean(ProductOrderFactory.class));
}
orderService.set(orderFactory.get().createOrder());
return order;
}
}
dao,mapper略