1. 程式人生 > >用工廠方法模式來下不同訂單

用工廠方法模式來下不同訂單

現在假設我們有兩種型別的訂單,汽車服務訂單和商城配件訂單

我們的抽象訂單介面為

public interface Order {
    public void makeOrder(Order order);
}

抽象訂單工廠介面為

public interface OrderFactory {
    public Order createOrder();
}

現有具體的汽車服務型別訂單

@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版本號如下

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceOrderVersion {
    int value();
}

商城配件訂單略

具體汽車服務工廠,我們將其注入Spring容器,不需要每次下單的時候都去掃描包

@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進行保護。

@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;
    }
}