zoukankan      html  css  js  c++  java
  • 优雅的代码之选择不同支付方式

    如何写出优雅的代码
    我在这里举一个例子,当你选择一个商品时,对应的不同的支付方式,可以选择不同的支付方式,比如你可以选择农业银行支付可以享受打8折的优惠,选择建设银行支付可以享受打9折的优惠。
    又比如同样一份文件,客户可以选择以word文件的形式下载,或者以pdf文件的格式下载,或者以Excel的文件格式下载。。。
    其实有很对业务场景是这样的,我就不一一举例了,就拿第一个例子来说:
    不同的银行都需要一个支付的功能,不同的银行各自的实现。前端页面传入一个银行id,此时我们需要通过这个银行id找到具体的实例对象。

    key/value其中key是银行id,value是对应的实现类
    实现类
    实现类
    strategyFactory
    context
    strategy pay的方法
    农业银行
    建设银行
    这里key/value存的是银行id和对应的实现类,这里我们可以采用xml配置文件的方式,也可以采用自定义注解的方式。
    这是银行表
    这是对应的商品表
    下面展示源码,对应的mapper和pojo这里就不展示了
    首先写一个接口,这个接口有一个计算的方法,

    public interface Strategy {
    //其中goodsId为商品id,bankid为银行id
    public double count(int goodsId,int bankId);

    }
    1
    2
    3
    4
    5
    下面是它的两个实现类
    这个是农业银行的实现类

    @Component
    @Pay(value=1)
    public class NHbank implements Strategy{

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private BankMapper bankMapper;
    @Override
    public double count(int goodsId, int bankId) {
    // TODO Auto-generated method stub
    Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
    Bank bank = bankMapper.selectByPrimaryKey(bankId);
    System.out.println("我选择的是农业银行帮我付款");
    return bank.getCount()*goods.getPrice();
    }

    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    下面是建设银行实现类

    package cn.haha.ssm.service;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;

    import cn.haha.ssm.mapper.BankMapper;
    import cn.haha.ssm.mapper.GoodsMapper;
    import cn.haha.ssm.po.Bank;
    import cn.haha.ssm.po.Goods;
    import cn.haha.ssm.utils.Pay;
    import cn.haha.ssm.utils.Strategy;

    @Component
    @Pay(value=2)
    public class JSbank2 implements Strategy{

    @Autowired
    private GoodsMapper goodsMapper;

    @Autowired
    private BankMapper bankMapper;
    @Override
    public double count(int goodsId, int bankId) {
    // TODO Auto-generated method stub
    Goods goods = goodsMapper.selectByPrimaryKey(goodsId);
    Bank bank = bankMapper.selectByPrimaryKey(bankId);
    System.out.println("我选择的是建设银行帮我付款");
    return bank.getCount()*goods.getPrice();
    }

    }

    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
    下面是自定义注解类

    package cn.haha.ssm.utils;

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    我们通过自定义注解类实例化对应的对象

    package cn.haha.ssm.utils;

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;

    import org.reflections.Reflections;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.stereotype.Component;


    public class StrategyFactory {
    private static StrategyFactory strategyFactory=new StrategyFactory();
    private StrategyFactory(){

    }
    public static StrategyFactory newInstance(){
    return strategyFactory;
    }
    public static Map<Integer, String> sourceMap=new HashMap<>();

    static{
    //扫描含有自定义注解的包
    Reflections reflections = new Reflections("cn.haha.ssm.service");
    //将包中含有注解pay的类取出来
    Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(Pay.class);
    for (Class<?> class1 : typesAnnotatedWith) {
    Pay pay = class1.getAnnotation(Pay.class);
    //将银行bankId和对应的实体类放在map集合中
    sourceMap.put(pay.value(),class1.getCanonicalName());
    }
    }

    public Strategy create(int bankId) throws Exception{
    ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    //根据bankId得到对应的实现类。并实例化对象
    String clazz = sourceMap.get(bankId);
    Class<?> forName = Class.forName(clazz);
    return (Strategy) applicationContext.getBean(forName);
    }
    }

    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
    下面计算打完折不同支付方式需要支付的金额

    @Component
    public class Context {
    public double count(int goodsId,int bankId) throws Exception{
    StrategyFactory strategyFactory = StrategyFactory.newInstance();
    Strategy strategy = strategyFactory.create(bankId);
    return strategy.count(goodsId, bankId);
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    我们需要将自己定义的类交给spring容器进行管理,不然会出现注入失败的问题
    当然我们也可以实现ApplicationContextAware接口,当一个类实现了这个接口之后,这个类就可以方便的获取ApplicationContext中的所有的bean。使用这类很简单

    package cn.haha.ssm.utils;

    import java.lang.reflect.Field;

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;

    public class BeanUtils implements ApplicationContextAware{
    private static ApplicationContext context;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    // TODO Auto-generated method stub
    this.context=applicationContext;
    }

    public static ApplicationContext getContext(){
    return context;
    }

    public static void initBank(Class clazz) throws Exception{
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
    //获取成员变量的类名
    String simpleName = field.getType().getSimpleName();
    //把类名的首字母改为小写
    String topString = simpleName.substring(0, 1);
    String lowerCase = topString.toLowerCase();
    String beanName=lowerCase+simpleName.substring(1);
    Object bean = context.getBean(beanName);
    field.setAccessible(true);
    field.set(this,bean);
    }
    }
    }

    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
    之所以我们能如此方便的使用该工具来获取,正是因为Spring能过为我们自动的执行setApplicationContext方法,显然,这也是因为IOC的缘故,所以这个工具类也是需要在Spring的配置文件中进行配置的。
    ---------------------

  • 相关阅读:
    如何用Tensorflow训练模型成pb文件和和如何加载已经训练好的模型文件
    hbase rowkey 设计
    hbase集群region数量和大小的影响
    为什么不建议在hbase中使用过多的列簇
    hive explode 行拆列
    通过livy向CDH集群的spark提交任务
    case when多条件
    spark sql/hive小文件问题
    SQL join
    spark任务调度模式,动态资源分配
  • 原文地址:https://www.cnblogs.com/ly570/p/11076069.html
Copyright © 2011-2022 走看看