泛型在代码设计中的思考

泛型在代码设计中的思考
简介

最近查看了Hibernate Validator泛型的使用和认知有了新的理解,这里结合自己的理解做一个总结。

JAVA 的类型
                      ┌────┐
                      │Type│
                      └────┘
                         ▲
                         │
   ┌────────────┬────────┴─────────┬───────────────┬──────────────┐
   │            │                  │               │              │
┌─────┐┌─────────────────┐┌────────────────┐┌────────────┐  ┌────────────┐
│Class││ParameterizedType││GenericArrayType││WildcardType│  │TypeVariable│
└─────┘└─────────────────┘└────────────────┘└────────────┘  └────────────┘

以上是目前java的类系统结构,我们接触最多的是Class类型,但是有了泛型后光只有Class类型是不够的所以java又进一步多抽象出了以下几种类型

  • ParameterizedType

    带泛型的参数比如 List

  • GenericArrayType

    泛型数据比如 T[]

  • WildcardType

    通配符 如List<? extends Number>里的 ?

  • TypeVariable

    类型变量,例如 List中的 T

泛型小结
  • 不能是基本类型,例如:int
  • 不能获取带泛型类型的Class,例如:Pair<String>.class
  • 不能判断带泛型类型的类型,例如:x instanceof Pair<String>
  • 不能实例化T类型,例如:new T()
  • 子类可以获取父类的泛型类型<T>
关于在设计中的思考
工厂模式

最早在做一系列策略的时候会使用工厂模式,根据入参来在工厂中做ifelse的判断如下

public Strategy getStrategy(int type){
        if(type==1){
            return new Strategy1();
        }else if (type==2){
            return new Strategy2();
        }
        return new DefaultStrategy();
    }

Strategy是一个接口,而Strategy1Strategy2, DefaultStrategyStrategy的实现类

这样ifelse并没有消失而是放在了工厂方法里,而不是放在业务中,这样方便维护一些,在简单的业务条件中这是一个不错的实现,因为够简单,一看就懂,但是随着业务复杂度增加,即使我们抽象出了工厂类或者工厂方法,但是随着ifelse的增多,代码也逐渐出现了坏味道,于是又出现了责任链模式。

责任链模式

其也是Spring中广泛使用的设计模式,其使用遍历的方式间接代替了ifelse,其代码通常会定义一个Handler和一个Invoker和一个Commond

 interface Handler{

        void handle();
        
        boolean support(Commond commond);

    }
 interface Commond{

    }
class Invoker(){
        private List<Handler> repository;
        void invoke(Commond commond){
            for (Handler handler:repository){
                if(handler.support(commond)){
                    handler.handle();
                }
            }
        }
    }

其核心逻辑就定义一个处理器Handler里面包含一个support方法,该方法去判断这个处理器能处理什么样的Commond命令,然后使用者只需要使用Invoker,传入对应的Commnd就可以完成整个责任链的调用。这里及时业务再复杂我们也只需要上面一个if就可以解决,

这是一个典型的空间换复杂度的做法,毕竟遍历肯定比if和else耗时,但是还是那句话,究竟多慢才是慢?只要在合理客接受范围内我觉得时间换复杂度就是一种血赚的行为,何况上面这种做法在List不大时也很快

泛型模式

其实并没有这种模式,这只是我查看Hibernate Validator源码后自己瞎起的,我们利用泛型小结中的最后一点子类可以获取父类的泛型类型<T> 可以设计出一种基于反射的模式来完成业务的解耦,而不是采用编码的方式(责任链模式中的support方法)话不多说上代码

/**
 * @author Liush
 * @description 用户请求抽象类
 * @date 2021/11/23 17:44
 **/
public interface Command {
}

/**
 * @author Liush
 * @description 用户请求实现类
 * @date 2021/11/24 9:12
 **/
public class Command1 implements Command {
}
/**
 * @author Liush
 * @description 策略类
 * @date 2021/11/23 17:36
 **/
public abstract class Strategy<T> {

    void handle(T t) {

    }
}
/**
 * @author Liush
 * @description 策略实现类
 * @date 2021/11/23 17:38
 **/
public class Strategy1 extends Strategy<Command1> {
    @Override
    public void handle(Command1 command1) {
        System.out.println("do something");
    }
}
/**
 * @author Liush
 * @description 使用示例
 * @date 2021/11/23 17:43
 **/
public class GenericHandle {

    public HashMap<String,Strategy> repository;

    public GenericHandle(){
        //初始化泛型策略,这部分后续可采用配置或者注解去实现策略的注入,读取策略类的泛型,存入缓存仓库
        repository=new HashMap<>();
        Type type =Strategy1.class.getGenericSuperclass();
        if(type instanceof ParameterizedType){
            ParameterizedType parameterizedType=(ParameterizedType)type;
            String key=parameterizedType.getActualTypeArguments()[0].getTypeName();
            repository.put(key,new Strategy1());
        }

    }
	//根据用户传来的命令Command,执行不同的策略
    public void handle(Command command){
        Strategy strategy=repository.get(command.getClass().getName());
        strategy.handle(command);
    }

	//使用实例
    public static void main(String[] args) {
        GenericHandle genericHandle=new GenericHandle();
        Command1 command=new Command1();
        genericHandle.handle(command);
    	}

}
总结

其实采用泛型和责任链的区别就是,责任链还是依靠编码(主要依靠support方法),而采用泛型的话则是更多依赖反射,这种方式各有千秋,采用责任链代码可读性更强,而采用反射则是代码更加灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值