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

如今假設咱們有兩種類型的訂單,汽車服務訂單和商城配件訂單安全

咱們的抽象訂單接口爲app

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

抽象訂單工廠接口爲dom

public interface OrderFactory {
    public Order createOrder();
    public Order getOrder();
}

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

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

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

商城配件訂單略this

具體汽車服務工廠,咱們將其注入Spring容器,不須要每次下單的時候都去掃描包,過濾規則spa

@Component
public class ServiceOrderFactory implements OrderFactory {
    private Set<Class<?>> classes = ClassUtil.getClassSet("com.cloud.ownercar.domain");
    private Order createdOrder;

    @PostConstruct
    private void initOrder() {
        this.createdOrder = createOrder();
    }

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

    @Override
    public Order getOrder() {
        return createdOrder;
    }
}

具體配件工廠略線程

另外爲了知足開閉原則,咱們須要加載全部類型的訂單和訂單工廠,之後在新增訂單類型的時候,只須要在指定包下追加新的類型就好。code

@Component
public class OrderBean {
    @Getter
    private Map<String,Class<?>> orderFactoryMap = new HashMap<>();
    @Getter
    private Map<String,Class<?>> orderMap = new HashMap<>();

    @PostConstruct
    private void init() {
        Set<Class<?>> classes = ClassUtil.getClassSet("com.cloud.ownercar.domain");
        classes.stream().filter(clazz -> OrderFactory.class.isAssignableFrom(clazz))
                .forEach(clazz -> orderFactoryMap.put(clazz.getSimpleName(),clazz));
        classes.stream().filter(clazz -> Order.class.isAssignableFrom(clazz))
                .forEach(clazz -> orderMap.put(clazz.getSimpleName(),clazz));
    }
}

Controller以下,用傳遞的內容來判斷是哪一種類型的訂單,並給抽象訂單工廠來獲取具體的訂單工廠,經過具體的訂單工廠來生成訂單服務,完成下單功能。考慮到線程安全問題,因此要加ThreadLocal進行保護。這個type是在下單的時候須要提供的訂單類型,好比"ServiceOrder"或者"ProductOrder"或者之後新增的訂單類型。對象

@Slf4j
@RestController
public class OrderController {
    private ThreadLocal<OrderFactory> orderFactory = new ThreadLocal<>();
    private ThreadLocal<Order> orderService = new ThreadLocal<>();
    @Autowired
    private OrderBean orderBean;

    @Transactional
    @SuppressWarnings("unchecked")
    @PostMapping("/makeeorder")
    public Result<String> makeOrder(@RequestBody String orderStr, @RequestParam("type") String type) {
        log.info(orderStr);
        try {
            Order order = setOrderFactory(orderStr,type);
            orderService.get().makeOrder(order);
            return Result.success("下單成功");
        }
        finally {
            orderFactory.remove();
            orderService.remove();
        }
    }

    /**
     * 判斷是哪種類型的訂單來獲取哪種類型的具體訂單工廠
     * @param orderStr
     * @return
     */
    private Order setOrderFactory(String orderStr,String type) {
        Class<?> classType = orderBean.getOrderMap().get(type);
        Object order = JSONObject.parseObject(orderStr, classType);
//        if (orderStr.contains("service")) {
//            order = JSON.parseObject(orderStr, ServiceOrder.class);
//        }else if (orderStr.contains("product")) {
//            order = JSON.parseObject(orderStr, ProductOrder.class);
//        }
        Class<?> classFactoryType = orderBean.getOrderFactoryMap().get(type + "Factory");
        this.orderFactory.set((OrderFactory) SpringBootUtil.getBean(classFactoryType));
//        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().getOrder());
        return (Order) order;
    }
}

dao,mapper略

相關文章
相關標籤/搜索