我們如何能根據一個業務來優雅的實現高擴展性,可維護性高的代碼呢,下面介紹一種我們常用的設計模式--工廠模式
具體代碼實現:
sql腳本:
create table channel
(
channel_id int auto_increment
primary key,
channel_name varchar(40) null
comment '渠道名稱',
simple_name varchar(20) null
comment '渠道簡稱',
dis_count int null
comment '渠道折扣',
status varchar(20) null
comment '渠道開啓狀態'
)
comment '支付渠道表';
INSERT INTO `channel`(`channel_id`, `channel_name`, `simple_name`, `dis_count`, `status`) VALUES (1, '中國農業銀行', 'ABC', '1', 'open');
INSERT INTO `channel`(`channel_id`, `channel_name`, `simple_name`, `dis_count`, `status`) VALUES (2, '中國工商銀行', 'ICBC', '0.91', 'open');
INSERT INTO `channel`(`channel_id`, `channel_name`, `simple_name`, `dis_count`, `status`) VALUES (3, '中國郵政儲蓄銀行', 'PSBC', '0.5', 'open');
create table goods
(
goods_id int auto_increment
comment 'id'
primary key,
goods_name varchar(50) null
comment '商品名稱',
abstracts varchar(500) null
comment '商品簡介',
status varchar(50) null
comment '商品狀態',
price int null
comment '商品價格'
)
comment '商品表';
INSERT INTO `goods`(`goods_id`, `goods_name`, `abstracts`, `status`, `price`) VALUES (1, '深入理解JVM', 'Java高級', '已上架', 55);
java代碼:
package tjs.bf.beans.pay;
import lombok.Data;
import lombok.ToString;
import tjs.bf.beans.BaseBean;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
@Data
@ToString
public class Goods extends BaseBean {
private Integer goodsId;
private String goodsName;
private BigDecimal price;
private String abstracts;
private String status;
}
package tjs.bf.beans.pay;
import lombok.Data;
import lombok.ToString;
import tjs.bf.beans.BaseBean;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
@Data
@ToString
public class Channel extends BaseBean {
private Integer ChannelId;
private String ChannelName;
private String simpleName;
private BigDecimal disCount;
private String status;
}
package tjs.bf.api.impl.pay;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
@Target(ElementType.TYPE)//類註解
@Retention(RetentionPolicy.RUNTIME)//在JAM中可以取到
public @interface Pay {
int channelId();
}
package tjs.bf.api.impl.pay;
import org.springframework.beans.factory.annotation.Autowired;
import tjs.bf.beans.pay.Channel;
import tjs.bf.beans.pay.Goods;
import tjs.bf.config.ApplicationContextHelper;
import tjs.bf.mapper.pay.ChannelMapper;
import tjs.bf.mapper.pay.GoodsMapper;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc: 中國農業銀行
*/
@Pay(channelId = 1)
public class ABCbank extends ApplicationContextHelper implements Strategy {
@Resource
private GoodsMapper goodsMapper;
@Resource
private ChannelMapper channelMapper;
@Override
public BigDecimal calPrice(int channelId, int goodsId) {
Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
Channel channel = channelMapper.selectByPrimaryKey(channelId);
return channel.getDisCount().multiply(goods.getPrice());
}
}
package tjs.bf.api.impl.pay;
import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import tjs.bf.beans.pay.Channel;
import tjs.bf.beans.pay.Goods;
import tjs.bf.config.ApplicationContextHelper;
import tjs.bf.mapper.pay.ChannelMapper;
import tjs.bf.mapper.pay.GoodsMapper;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc: 中國工商銀行
*/
@Pay(channelId = 2)
public class ICBCBank extends ApplicationContextHelper implements Strategy {
@Resource
private GoodsMapper goodsMapper;
@Resource
private ChannelMapper channelMapper;
@Override
public BigDecimal calPrice(int channelId, int goodsId) {
Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
Channel channel = channelMapper.selectByPrimaryKey(channelId);
return channel.getDisCount().multiply(goods.getPrice());
}
}
package tjs.bf.api.impl.pay;
import org.springframework.beans.factory.annotation.Autowired;
import tjs.bf.beans.pay.Channel;
import tjs.bf.beans.pay.Goods;
import tjs.bf.config.ApplicationContextHelper;
import tjs.bf.mapper.pay.ChannelMapper;
import tjs.bf.mapper.pay.GoodsMapper;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc: 中國郵政儲蓄銀行
*/
@Pay(channelId = 3)
public class PSBCbank extends ApplicationContextHelper implements Strategy {
@Resource
private GoodsMapper goodsMapper;
@Resource
private ChannelMapper channelMapper;
@Override
public BigDecimal calPrice(int channelId, int goodsId) {
Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
Channel channel = channelMapper.selectByPrimaryKey(channelId);
return channel.getDisCount().multiply(goods.getPrice());
}
}
package tjs.bf.api.impl.pay;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
public interface Strategy {
//計算採用不同渠道商品的優惠價格
BigDecimal calPrice(int channelId, int goodsId);
}
package tjs.bf.api.impl.pay;
import org.reflections.Reflections;
import java.util.HashMap;
import java.util.Set;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc: 工廠類
*/
public class StrategyFactory {
private static StrategyFactory factory = new StrategyFactory();
private static HashMap<Integer,String> source_map = new HashMap<>();
private StrategyFactory(){}
/**
* @desc: 根據我們渠道ID創建所需要的實現類
* @author: SJT
* @date: 2019/3/18
* @param: [channelId]
* @return: tjs.bf.api.impl.pay.Strategy
*/
public Strategy create(int channelId) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String clazz = source_map.get(channelId);
Class<?> clazz_ = Class.forName(clazz);
return (Strategy) clazz_.newInstance();
}
/**
* @desc: 利用反射來獲取自定義類註解中渠道ID,將我們渠道ID與相對應的實現類相關聯放進我們維護的Map裏
* @author: SJT
* @date: 2019/3/18
* @param:
* @return:
*/
static {
Reflections reflections = new Reflections("tjs.bf.api.impl.pay");
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(Pay.class);
classSet.stream().forEach(clazz ->{
Pay pay = clazz.getAnnotation(Pay.class);
source_map.put(pay.channelId(),clazz.getCanonicalName());
});
}
/**
* @desc: 獲取工廠實例
* @author: SJT
* @date: 2019/3/18
* @param: []
* @return: tjs.bf.api.impl.pay.StrategyFactory
*/
public static StrategyFactory getInstance(){
return factory;
}
}
package tjs.bf.api.impl.pay;
import com.alibaba.dubbo.config.annotation.Service;
import tjs.bf.api.PayService;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc: 支付接口實現類
*/
@Service
public class PayServiceImpl implements PayService {
@Override
public BigDecimal calPrice(int channelId, int goodsId) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Strategy strategy = StrategyFactory.getInstance().create(channelId);
return strategy.calPrice(channelId,goodsId);
}
}
package tjs.bf.api;
import java.math.BigDecimal;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
public interface PayService {
public BigDecimal calPrice(int channelId,int goodsId) throws IllegalAccessException, InstantiationException, ClassNotFoundException;
}
package tjs.bf.controller.pay;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tjs.bf.api.PayService;
import tjs.bf.common.JsonData;
/**
* @project: springboot-dubbo-parent
* @author: SJT
* @date: 2019/3/17
* @desc:
*/
@RestController
@RequestMapping("/pay")
public class PayController {
@Reference
PayService payService;
@GetMapping("/pay")
public JsonData pay(Integer channelId,Integer goodsId) throws IllegalAccessException, ClassNotFoundException, InstantiationException {
return JsonData.success(payService.calPrice(channelId,goodsId));
}
}
ok到此結束,有興趣的可以試試~.~